<commit_before>/* This file is part of the KDE libraries
   Copyright (C) 2002 Anders Lund <anders@alweb.dk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   $Id$
*/

#include "insertfileplugin.h"
#include "insertfileplugin.moc"

#include <ktexteditor/document.h>
#include <ktexteditor/viewcursorinterface.h>
#include <ktexteditor/editinterface.h>

#include <assert.h>
#include <kio/job.h>
#include <kaction.h>
#include <kfiledialog.h>
#include <kgenericfactory.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <ktempfile.h>
#include <kurl.h>

#include <qfile.h>
#include <qtextstream.h>

K_EXPORT_COMPONENT_FACTORY( ktexteditor_insertfile, KGenericFactory<InsertFilePlugin>( "ktexteditor_insertfile" ) );

//BEGIN InsertFilePlugin
InsertFilePlugin::InsertFilePlugin( QObject *parent, const char* name, const QStringList& )
	: KTextEditor::Plugin ( (KTextEditor::Document*) parent, name )
{
}

InsertFilePlugin::~InsertFilePlugin()
{
}

void InsertFilePlugin::addView(KTextEditor::View *view)
{
  InsertFilePluginView *nview = new InsertFilePluginView (view, "Insert File Plugin");
  m_views.append (nview);
}

void InsertFilePlugin::removeView(KTextEditor::View *view)
{
  for (uint z=0; z < m_views.count(); z++)
    if (m_views.at(z)->parentClient() == view)
    {
       InsertFilePluginView *nview = m_views.at(z);
       m_views.remove (nview);
       delete nview;
    }
}
//END InsertFilePlugin

//BEGIN InsertFilePluginView
InsertFilePluginView::InsertFilePluginView( KTextEditor::View *view, const char *name )
  : QObject( view, name ),
    KXMLGUIClient( view )
{
  view->insertChildClient( this );
  setInstance( KGenericFactory<InsertFilePlugin>::instance() );
  _job = 0;
  (void) new KAction( i18n("Insert File..."), 0, this, SLOT(slotInsertFile()), actionCollection(), "tools_insert_file" );
  setXMLFile( "ktexteditor_insertfileui.rc" );
}

void InsertFilePluginView::slotInsertFile()
{
  _file = KFileDialog::getOpenURL( "::insertfile", "",
                                             (QWidget*)parent(),
                                             i18n("Choose File to Insert") ).url();
  if ( _file.isEmpty() ) return;

  if ( _file.isLocalFile() ) {
    _tmpfile = _file.fileName();
    insertFile();
  }
  else {
    KTempFile tempFile( QString::null );
    _tmpfile = tempFile.name();

    KURL destURL;
    destURL.setPath( _tmpfile );
    _job = KIO::file_copy( _file, destURL, 0600, true, false, true );
    connect( _job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinished ( KIO::Job * ) ) );
  }
}

void InsertFilePluginView::slotFinished( KIO::Job *job )
{
  assert( job == _job );
  _job = 0;
  if ( job->error() )
    KMessageBox::error( (QWidget*)parent(), i18n("Failed to load file:\n\n") + job->errorString(), i18n("Insert File error") );
  else
    insertFile();
}

void InsertFilePluginView::insertFile()
{
  QString error;
  if ( _tmpfile.isEmpty() )
    error = i18n("
The file %1 is empty, aborting.").arg(_file.fileName());

  QFileInfo fi;
  fi.setFile( _tmpfile );
  if (!fi.exists() || !fi.isReadable())
    error = i18n("
The file %1 does not exist or is not readable, aborting.").arg(_file.fileName());

  QFile f( _tmpfile );
  if ( !f.open(IO_ReadOnly) )
    error = i18n("
Unable to open file %1, aborting.").arg(_file.fileName());

  if ( ! error.isEmpty() ) {
    KMessageBox::sorry( (QWidget*)parent(), error, i18n("Insert file error") );
    return;
  }

  // now grab file contents
  QTextStream stream(&f);
  QString str, tmp;
  uint numlines = 0;
  uint len = 0;
  while (!stream.eof()) {
    if ( numlines )
      str += "\n";
    tmp = stream.readLine();
    str += tmp;
    len = tmp.length();
    numlines++;
  }
  f.close();

  if ( str.isEmpty() )
    error = i18n("
File %1 had no contents.").arg(_file.fileName());
  if ( ! error.isEmpty() ) {
    KMessageBox::sorry( (QWidget*)parent(), error, i18n("Insert file error") );
    return;
  }

  // insert !!
  KTextEditor::EditInterface *ei;
  KTextEditor::ViewCursorInterface *ci;
  KTextEditor::View *v = (KTextEditor::View*)parent();
  ei = KTextEditor::editInterface( v->document() );
  ci = KTextEditor::viewCursorInterface( v );
  uint line, col;
  ci->cursorPositionReal( &line, &col );
  ei->insertText( line, col, str );

  // move the cursor
  ci->setCursorPositionReal( line + numlines - 1, numlines > 1 ? len : col + len  );

  // clean up
  _file = KURL ();
  _tmpfile.truncate( 0 );
  v = 0;
  ei = 0;
  ci = 0;
}

//END InsertFilePluginView

<commit_msg>fixing to wrok with local files [how embarrassing..]<commit_after>/* This file is part of the KDE libraries
   Copyright (C) 2002 Anders Lund <anders@alweb.dk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   $Id$
*/

#include "insertfileplugin.h"
#include "insertfileplugin.moc"

#include <ktexteditor/document.h>
#include <ktexteditor/viewcursorinterface.h>
#include <ktexteditor/editinterface.h>

#include <assert.h>
#include <kio/job.h>
#include <kaction.h>
#include <kfiledialog.h>
#include <kgenericfactory.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <ktempfile.h>
#include <kurl.h>

#include <qfile.h>
#include <qtextstream.h>

K_EXPORT_COMPONENT_FACTORY( ktexteditor_insertfile, KGenericFactory<InsertFilePlugin>( "ktexteditor_insertfile" ) );

//BEGIN InsertFilePlugin
InsertFilePlugin::InsertFilePlugin( QObject *parent, const char* name, const QStringList& )
	: KTextEditor::Plugin ( (KTextEditor::Document*) parent, name )
{
}

InsertFilePlugin::~InsertFilePlugin()
{
}

void InsertFilePlugin::addView(KTextEditor::View *view)
{
  InsertFilePluginView *nview = new InsertFilePluginView (view, "Insert File Plugin");
  m_views.append (nview);
}

void InsertFilePlugin::removeView(KTextEditor::View *view)
{
  for (uint z=0; z < m_views.count(); z++)
    if (m_views.at(z)->parentClient() == view)
    {
       InsertFilePluginView *nview = m_views.at(z);
       m_views.remove (nview);
       delete nview;
    }
}
//END InsertFilePlugin

//BEGIN InsertFilePluginView
InsertFilePluginView::InsertFilePluginView( KTextEditor::View *view, const char *name )
  : QObject( view, name ),
    KXMLGUIClient( view )
{
  view->insertChildClient( this );
  setInstance( KGenericFactory<InsertFilePlugin>::instance() );
  _job = 0;
  (void) new KAction( i18n("Insert File..."), 0, this, SLOT(slotInsertFile()), actionCollection(), "tools_insert_file" );
  setXMLFile( "ktexteditor_insertfileui.rc" );
}

void InsertFilePluginView::slotInsertFile()
{
  _file = KFileDialog::getOpenURL( "::insertfile", "",
                                             (QWidget*)parent(),
                                             i18n("Choose File to Insert") ).url();
  if ( _file.isEmpty() ) return;

  if ( _file.isLocalFile() ) {
    _tmpfile = _file.path();
    insertFile();
  }
  else {
    KTempFile tempFile( QString::null );
    _tmpfile = tempFile.name();

    KURL destURL;
    destURL.setPath( _tmpfile );
    _job = KIO::file_copy( _file, destURL, 0600, true, false, true );
    connect( _job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinished ( KIO::Job * ) ) );
  }
}

void InsertFilePluginView::slotFinished( KIO::Job *job )
{
  assert( job == _job );
  _job = 0;
  if ( job->error() )
    KMessageBox::error( (QWidget*)parent(), i18n("Failed to load file:\n\n") + job->errorString(), i18n("Insert File error") );
  else
    insertFile();
}

void InsertFilePluginView::insertFile()
{
  QString error;
  if ( _tmpfile.isEmpty() )
    return;

  QFileInfo fi;
  fi.setFile( _tmpfile );
  if (!fi.exists() || !fi.isReadable())
    error = i18n("
The file %1 does not exist or is not readable, aborting.").arg(_file.fileName());

  QFile f( _tmpfile );
  if ( !f.open(IO_ReadOnly) )
    error = i18n("
Unable to open file %1, aborting.").arg(_file.fileName());

  if ( ! error.isEmpty() ) {
    KMessageBox::sorry( (QWidget*)parent(), error, i18n("Insert file error") );
    return;
  }

  // now grab file contents
  QTextStream stream(&f);
  QString str, tmp;
  uint numlines = 0;
  uint len = 0;
  while (!stream.eof()) {
    if ( numlines )
      str += "\n";
    tmp = stream.readLine();
    str += tmp;
    len = tmp.length();
    numlines++;
  }
  f.close();

  if ( str.isEmpty() )
    error = i18n("
File %1 had no contents.").arg(_file.fileName());
  if ( ! error.isEmpty() ) {
    KMessageBox::sorry( (QWidget*)parent(), error, i18n("Insert file error") );
    return;
  }

  // insert !!
  KTextEditor::EditInterface *ei;
  KTextEditor::ViewCursorInterface *ci;
  KTextEditor::View *v = (KTextEditor::View*)parent();
  ei = KTextEditor::editInterface( v->document() );
  ci = KTextEditor::viewCursorInterface( v );
  uint line, col;
  ci->cursorPositionReal( &line, &col );
  ei->insertText( line, col, str );

  // move the cursor
  ci->setCursorPositionReal( line + numlines - 1, numlines > 1 ? len : col + len  );

  // clean up
  _file = KURL ();
  _tmpfile.truncate( 0 );
  v = 0;
  ei = 0;
  ci = 0;
}

//END InsertFilePluginView

<|endoftext|>


<commit_before>#include "variant/usart_platform.hpp"

#include "hal.h"

// UART2 configuration (XBee)
static const SerialConfig UART2_CONFIG {
  38400,
  0,
  USART_CR2_STOP1_BITS | USART_CR2_LINEN,
  0
};

// UART4 configuration (Unused)
static const SerialConfig UART4_CONFIG {
  115200,
  0,
  USART_CR2_STOP1_BITS | USART_CR2_LINEN,
  0
};

// UART6 configuration (GPS)
static const SerialConfig UART6_CONFIG {
  9600,
  0,
  USART_CR2_STOP1_BITS | USART_CR2_LINEN,
  0
};

USARTPlatform::USARTPlatform() {
  // Force RX high on startup to prevent XBee from entering SPI mode
  palSetPadMode(GPIOA, 3, PAL_MODE_OUTPUT_PUSHPULL);   // RX
  palSetPad(GPIOA, 3);
  chThdSleepMilliseconds(500);

  // UART2
  sdStart(&SD2, &UART2_CONFIG);
  palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));   // TX
  palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));   // RX

  // UART4
  sdStart(&SD4, &UART4_CONFIG);
  palSetPadMode(GPIOA, 0, PAL_MODE_ALTERNATE(8));   // TX
  palSetPadMode(GPIOA, 1, PAL_MODE_ALTERNATE(8));   // RX

  // UART6
  sdStart(&SD6, &UART6_CONFIG);
  palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(8));   // TX
  palSetPadMode(GPIOC, 7, PAL_MODE_ALTERNATE(8));   // RX
}

chibios_rt::BaseSequentialStreamInterface& USARTPlatform::getPrimaryStream() {
  return reinterpret_cast<chibios_rt::BaseSequentialStreamInterface&>(SD2);
}
<commit_msg>Update GPS baudrate back to 115200.<commit_after>#include "variant/usart_platform.hpp"

#include "hal.h"

// UART2 configuration (XBee)
static const SerialConfig UART2_CONFIG {
  38400,
  0,
  USART_CR2_STOP1_BITS | USART_CR2_LINEN,
  0
};

// UART4 configuration (Unused)
static const SerialConfig UART4_CONFIG {
  115200,
  0,
  USART_CR2_STOP1_BITS | USART_CR2_LINEN,
  0
};

// UART6 configuration (GPS)
static const SerialConfig UART6_CONFIG {
  115200,
  0,
  USART_CR2_STOP1_BITS | USART_CR2_LINEN,
  0
};

USARTPlatform::USARTPlatform() {
  // Force RX high on startup to prevent XBee from entering SPI mode
  palSetPadMode(GPIOA, 3, PAL_MODE_OUTPUT_PUSHPULL);   // RX
  palSetPad(GPIOA, 3);
  chThdSleepMilliseconds(500);

  // UART2
  sdStart(&SD2, &UART2_CONFIG);
  palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));   // TX
  palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));   // RX

  // UART4
  sdStart(&SD4, &UART4_CONFIG);
  palSetPadMode(GPIOA, 0, PAL_MODE_ALTERNATE(8));   // TX
  palSetPadMode(GPIOA, 1, PAL_MODE_ALTERNATE(8));   // RX

  // UART6
  sdStart(&SD6, &UART6_CONFIG);
  palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(8));   // TX
  palSetPadMode(GPIOC, 7, PAL_MODE_ALTERNATE(8));   // RX
}

chibios_rt::BaseSequentialStreamInterface& USARTPlatform::getPrimaryStream() {
  return reinterpret_cast<chibios_rt::BaseSequentialStreamInterface&>(SD2);
}
<|endoftext|>


<commit_before>/*
 * SMD2Structs.cpp
 *
 *  Created on: 09.02.2016
 *      Author: Megacrafter127
 */

#include "SMD2Structs.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <zlib.h>
#include <stdexcept>

namespace smd2{
	block::block(const struct block *copy) {
		memcpy(this,copy,sizeof(struct block));
	};
	block::block(const unsigned int id, const unsigned int hp, const bool active, const unsigned int orientation) {
		this->id=id;
		this->hp=hp;
		this->active=active;
		this->orientation=orientation;
	};
	block::block(const rawBlock *raw, const blocktypeList *list) {
		if(!list) std::__throw_invalid_argument("the provided list may not be NULL");
		uint32_t buff=0;
		memcpy(&buff+sizeof(uint32_t)-sizeof(rawBlock),raw,sizeof(rawBlock));
		if(buff) {
			buff=ntohl(buff);
			this->id=buff;
			buff>>=11;
			blockType type=((blockType*)list)[this->id];
			if(type==undefined) {
				std::__throw_invalid_argument("blocktype not defined");
			}
			this->hp=buff;
			if(type==fullyRotating) {
				this->hp&=0x00FF;
				buff>>=8;
			} else buff>>=9;
			if(type==logic) {
				this->active=buff & 1;
				buff>>=1;
			}
			this->orientation=buff;
		} else {
			this->id=0;
			this->hp=0;
			this->active=false;
			this->orientation=0;
		}
	};
	block::block() {
		this->id=0;
		this->hp=0;
		this->active=false;
		this->orientation=0;
	};
	rawBlock *block::toRaw(rawBlock *target, const blocktypeList *list) {
		if(!list) std::__throw_invalid_argument("the provided list may not be NULL");
		blockType type=((blockType*)list)[this->id];
		if(type==undefined) {
			std::__throw_invalid_argument("blocktype not defined");
		}
		uint32_t buff=this->orientation;
		if(type==logic) {
			buff<<=1;
			if(this->active) buff++;
		}
		if(type==fullyRotating) {
			buff<<=8;
			buff+=(0xFF & this->hp);
		} else {
			buff<<=9;
			buff+=this->hp;
		}
		buff<<=11;
		buff+=id;
		buff=htonl(buff);
		memcpy(target,&buff+sizeof(uint32_t)-sizeof(rawBlock),sizeof(rawBlock));
		return target;
	};

	rawChunkData *inflate(rawChunkData *trg,const compressedChunkData *src) {}; //TODO #31
	compressedChunkData *deflate(compressedChunkData *trg,const rawChunkData *src) {}; //TODO #32
	bool isEmpty(const rawCompressedSegment *segment) {
		size_t *chars=(size_t*)segment;
		for(size_t i=0;i<(sizeof(rawCompressedSegment)/sizeof(size_t));i++) {
			if(chars[i]) return false;
		}
		return true;
	};

	segmentHead::segmentHead(const struct segmentHead *copy) {
		memcpy(this,copy,sizeof(struct segmentHead));
	};
	segmentHead::segmentHead(const unsigned char unknownChar, const unsigned long long timestamp, const signed long x, const signed long y, const signed long z, const unsigned char type, const unsigned long inlen) {
		this->unknownChar=unknownChar;
		this->timestamp=timestamp;
		this->x=x;
		this->y=y;
		this->z=z;
		this->type=type;
		this->inlen=inlen;
	};
	segmentHead::segmentHead(const rawCompressedSegment *raw,const bool offset) {
		size_t i=0;
		char *chars=(char*)raw;
		if(offset) {
			this->unknownChar=chars[i];
			i++;
		}
		uint64_t dbuff64;
		uint32_t *buff32=(uint32_t*)&dbuff64,dbuff32=ntohl(buff32[0]);
		memcpy(buff32,&(chars[i]),sizeof(uint64_t));
		if(ntohl(1)!=1) {
			buff32[0]=ntohl(buff32[1]);
			buff32[1]=dbuff32;
		}
		this->timestamp=dbuff64;
		i+=sizeof(uint64_t);

		memcpy(&dbuff32,&(chars[i]),sizeof(int32_t));
		this->x=ntohl(dbuff32);
		i+=sizeof(int32_t);

		memcpy(&dbuff32,&(chars[i]),sizeof(int32_t));
		this->y=ntohl(dbuff32);
		i+=sizeof(int32_t);

		memcpy(&dbuff32,&(chars[i]),sizeof(int32_t));
		this->z=ntohl(dbuff32);
		i+=sizeof(int32_t);

		this->type=chars[i];
		i++;

		memcpy(&dbuff32,&(chars[i]),sizeof(uint32_t));
		this->inlen=ntohl(dbuff32);
	};
	segmentHead::segmentHead() {
		this->unknownChar=0;
		this->timestamp=0;
		this->x=0;
		this->y=0;
		this->z=0;
		this->type=0;
		this->inlen=0;
	};
	rawCompressedSegment *segmentHead::toRaw(rawCompressedSegment *target,const bool offset) {
		size_t i=0;
		char *chars=(char*)target;
		if(offset) {
			chars[i]=this->unknownChar;
			i++;
		}
		uint64_t dbuff64=this->timestamp;
		uint32_t *buff32=(uint32_t*)&dbuff64,dbuff32=htonl(buff32[0]);
		if(htonl(1)!=1) {
			buff32[0]=htonl(buff32[1]);
			buff32[1]=dbuff32;
		}
		memcpy(&(chars[i]),buff32,sizeof(uint64_t));
		i+=sizeof(uint64_t);

		dbuff32=htonl(this->x);
		memcpy(&(chars[i]),&dbuff32,sizeof(int32_t));
		i+=sizeof(int32_t);

		dbuff32=htonl(this->y);
		memcpy(&(chars[i]),&dbuff32,sizeof(int32_t));
		i+=sizeof(int32_t);

		dbuff32=htonl(this->z);
		memcpy(&(chars[i]),&dbuff32,sizeof(int32_t));
		i+=sizeof(int32_t);

		this->type=chars[i];
		i++;

		dbuff32=htonl(this->inlen);
		memcpy(&(chars[i]),&dbuff32,sizeof(uint32_t));
		return target;
	};

	segment::segment(const struct segment *copy) {
		memcpy(this,copy,sizeof(struct segment));
	};
	segment::segment(const struct segmentHead *head,const chunkData *blocks) {}; //TODO #8
	segment::segment(const struct segmentHead *head,const rawChunkData *blocks) {}; //TODO #9
	segment::segment(const struct segmentHead *head,const compressedChunkData *blocks) {}; //TODO #10
	segment::segment(const struct rawSegment *src) {}; //TODO #9
	segment::segment(const struct compressedSegment *src) {}; //TODO #10
	segment::segment(const rawCompressedSegment *src) {}; //TODO #11
	rawCompressedSegment *segment::toRawCompressed(rawCompressedSegment *trg,const bool offset) {}; //TODO #12

	rawSegment::rawSegment(const struct rawSegment *copy) {
		memcpy(this,copy,sizeof(struct rawSegment));
	};
	rawSegment::rawSegment(const struct segmentHead *head,const rawChunkData*) {}; //TODO #14
	rawSegment::rawSegment(const struct segmentHead *head,const chunkData*) {}; //TODO #15
	rawSegment::rawSegment(const struct segmentHead *head,const compressedChunkData*) {}; //TODO #16
	rawSegment::rawSegment(const struct segment *src) {}; //TODO #15
	rawSegment::rawSegment(const struct compressedSegment *src) {}; //TODO #16
	rawSegment::rawSegment(const rawCompressedSegment *src) {}; //TODO #17
	rawCompressedSegment *rawSegment::toRawCompressed(rawCompressedSegment *trg,const bool offset) {}; //TODO #18

	compressedSegment::compressedSegment(const struct compressedSegment *copy) {
		memcpy(this,copy,sizeof(struct compressedSegment));
	};
	compressedSegment::compressedSegment(const struct segmentHead *head,const compressedChunkData *blocks) {}; //TODO #20
	compressedSegment::compressedSegment(const struct segmentHead *head,const chunkData *blocks) {}; //TODO #21
	compressedSegment::compressedSegment(const struct segmentHead *head,const rawChunkData *blocks) {}; //TODO #22
	compressedSegment::compressedSegment(const struct segment *src) {}; //TODO #21
	compressedSegment::compressedSegment(const struct rawSegment *src) {}; //TODO #22
	compressedSegment::compressedSegment(const rawCompressedSegment *src) {}; //TODO #23
	rawCompressedSegment *compressedSegment::toRawCompressed(rawCompressedSegment *trg,const bool offset) {}; //TODO #24

	smd2Index::smd2Index(const struct smd2Index *copy) {
		this->id=copy->id;
		this->inlen=copy->inlen;
	};
	smd2Index::smd2Index(const signed long id, const unsigned long len) {
		this->id=id;
		this->inlen=len;
	};
	smd2Index::smd2Index() {
		this->id=-1;
		this->inlen=0;
	};
	smd2Index::smd2Index(const rawSmd2Index *raw) {
		uint32_t split[2];
		memcpy(split,raw,sizeof(rawSmd2Index));
		this->id=ntohl(split[0]);
		this->inlen=ntohl(split[1]);
	};
	rawSmd2Index *smd2Index::toRaw(rawSmd2Index *trg) {
		uint32_t split[2];
		split[0]=htonl(this->id);
		split[1]=htonl(this->inlen);
		memcpy(trg,split,sizeof(rawSmd2Index));
		return trg;
	};
	bool smd2Index::isValid() {
		return this->id!=-1;
	};

	smd2Head::smd2Head(const struct smd2Head*) {}; //TODO #25
	smd2Head::smd2Head(const unsigned long version, const fullSmd2Index *index,const fullSmd2TimestampHead *timestamps) {
		this->version=version;
		memcpy(&(this->index),index,sizeof(fullSmd2Index));
		memcpy(&(this->timestamps),timestamps,sizeof(fullSmd2TimestampHead));
	};
	smd2Head::smd2Head(const rawSmd2Head*) {}; //TODO #26
	rawSmd2Head *smd2Head::toRaw(rawSmd2Head*) {}; //TODO #27

	unsigned int getSegmentSlotCountFromSMD2Size(const size_t) {}; //TODO #29
	size_t getSMD2SizeFromSegmentSlotCount(const unsigned int) {}; //TODO #30
}

<commit_msg>closed #8, closed #14, closed #20<commit_after>/*
 * SMD2Structs.cpp
 *
 *  Created on: 09.02.2016
 *      Author: Megacrafter127
 */

#include "SMD2Structs.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <zlib.h>
#include <stdexcept>

namespace smd2{
	block::block(const struct block *copy) {
		memcpy(this,copy,sizeof(struct block));
	};
	block::block(const unsigned int id, const unsigned int hp, const bool active, const unsigned int orientation) {
		this->id=id;
		this->hp=hp;
		this->active=active;
		this->orientation=orientation;
	};
	block::block(const rawBlock *raw, const blocktypeList *list) {
		if(!list) std::__throw_invalid_argument("the provided list may not be NULL");
		uint32_t buff=0;
		memcpy(&buff+sizeof(uint32_t)-sizeof(rawBlock),raw,sizeof(rawBlock));
		if(buff) {
			buff=ntohl(buff);
			this->id=buff;
			buff>>=11;
			blockType type=((blockType*)list)[this->id];
			if(type==undefined) {
				std::__throw_invalid_argument("blocktype not defined");
			}
			this->hp=buff;
			if(type==fullyRotating) {
				this->hp&=0x00FF;
				buff>>=8;
			} else buff>>=9;
			if(type==logic) {
				this->active=buff & 1;
				buff>>=1;
			}
			this->orientation=buff;
		} else {
			this->id=0;
			this->hp=0;
			this->active=false;
			this->orientation=0;
		}
	};
	block::block() {
		this->id=0;
		this->hp=0;
		this->active=false;
		this->orientation=0;
	};
	rawBlock *block::toRaw(rawBlock *target, const blocktypeList *list) {
		if(!list) std::__throw_invalid_argument("the provided list may not be NULL");
		blockType type=((blockType*)list)[this->id];
		if(type==undefined) {
			std::__throw_invalid_argument("blocktype not defined");
		}
		uint32_t buff=this->orientation;
		if(type==logic) {
			buff<<=1;
			if(this->active) buff++;
		}
		if(type==fullyRotating) {
			buff<<=8;
			buff+=(0xFF & this->hp);
		} else {
			buff<<=9;
			buff+=this->hp;
		}
		buff<<=11;
		buff+=id;
		buff=htonl(buff);
		memcpy(target,&buff+sizeof(uint32_t)-sizeof(rawBlock),sizeof(rawBlock));
		return target;
	};

	rawChunkData *inflate(rawChunkData *trg,const compressedChunkData *src) {}; //TODO #31
	compressedChunkData *deflate(compressedChunkData *trg,const rawChunkData *src) {}; //TODO #32
	bool isEmpty(const rawCompressedSegment *segment) {
		size_t *chars=(size_t*)segment;
		for(size_t i=0;i<(sizeof(rawCompressedSegment)/sizeof(size_t));i++) {
			if(chars[i]) return false;
		}
		return true;
	};

	segmentHead::segmentHead(const struct segmentHead *copy) {
		memcpy(this,copy,sizeof(struct segmentHead));
	};
	segmentHead::segmentHead(const unsigned char unknownChar, const unsigned long long timestamp, const signed long x, const signed long y, const signed long z, const unsigned char type, const unsigned long inlen) {
		this->unknownChar=unknownChar;
		this->timestamp=timestamp;
		this->x=x;
		this->y=y;
		this->z=z;
		this->type=type;
		this->inlen=inlen;
	};
	segmentHead::segmentHead(const rawCompressedSegment *raw,const bool offset) {
		size_t i=0;
		char *chars=(char*)raw;
		if(offset) {
			this->unknownChar=chars[i];
			i++;
		}
		uint64_t dbuff64;
		uint32_t *buff32=(uint32_t*)&dbuff64,dbuff32=ntohl(buff32[0]);
		memcpy(buff32,&(chars[i]),sizeof(uint64_t));
		if(ntohl(1)!=1) {
			buff32[0]=ntohl(buff32[1]);
			buff32[1]=dbuff32;
		}
		this->timestamp=dbuff64;
		i+=sizeof(uint64_t);

		memcpy(&dbuff32,&(chars[i]),sizeof(int32_t));
		this->x=ntohl(dbuff32);
		i+=sizeof(int32_t);

		memcpy(&dbuff32,&(chars[i]),sizeof(int32_t));
		this->y=ntohl(dbuff32);
		i+=sizeof(int32_t);

		memcpy(&dbuff32,&(chars[i]),sizeof(int32_t));
		this->z=ntohl(dbuff32);
		i+=sizeof(int32_t);

		this->type=chars[i];
		i++;

		memcpy(&dbuff32,&(chars[i]),sizeof(uint32_t));
		this->inlen=ntohl(dbuff32);
	};
	segmentHead::segmentHead() {
		this->unknownChar=0;
		this->timestamp=0;
		this->x=0;
		this->y=0;
		this->z=0;
		this->type=0;
		this->inlen=0;
	};
	rawCompressedSegment *segmentHead::toRaw(rawCompressedSegment *target,const bool offset) {
		size_t i=0;
		char *chars=(char*)target;
		if(offset) {
			chars[i]=this->unknownChar;
			i++;
		}
		uint64_t dbuff64=this->timestamp;
		uint32_t *buff32=(uint32_t*)&dbuff64,dbuff32=htonl(buff32[0]);
		if(htonl(1)!=1) {
			buff32[0]=htonl(buff32[1]);
			buff32[1]=dbuff32;
		}
		memcpy(&(chars[i]),buff32,sizeof(uint64_t));
		i+=sizeof(uint64_t);

		dbuff32=htonl(this->x);
		memcpy(&(chars[i]),&dbuff32,sizeof(int32_t));
		i+=sizeof(int32_t);

		dbuff32=htonl(this->y);
		memcpy(&(chars[i]),&dbuff32,sizeof(int32_t));
		i+=sizeof(int32_t);

		dbuff32=htonl(this->z);
		memcpy(&(chars[i]),&dbuff32,sizeof(int32_t));
		i+=sizeof(int32_t);

		this->type=chars[i];
		i++;

		dbuff32=htonl(this->inlen);
		memcpy(&(chars[i]),&dbuff32,sizeof(uint32_t));
		return target;
	};

	segment::segment(const struct segment *copy) {
		memcpy(this,copy,sizeof(struct segment));
	};
	segment::segment(const struct segmentHead *head,const chunkData *blocks) {
		this->head=*head;
		memcpy(&(this->blocks),blocks,sizeof(chunkData));
	};
	segment::segment(const struct segmentHead *head,const rawChunkData *blocks) {}; //TODO #9
	segment::segment(const struct segmentHead *head,const compressedChunkData *blocks) {}; //TODO #10
	segment::segment(const struct rawSegment *src) {}; //TODO #9
	segment::segment(const struct compressedSegment *src) {}; //TODO #10
	segment::segment(const rawCompressedSegment *src) {}; //TODO #11
	rawCompressedSegment *segment::toRawCompressed(rawCompressedSegment *trg,const bool offset) {}; //TODO #12

	rawSegment::rawSegment(const struct rawSegment *copy) {
		memcpy(this,copy,sizeof(struct rawSegment));
	};
	rawSegment::rawSegment(const struct segmentHead *head,const rawChunkData *blocks) {
		this->head=*head;
		memcpy(&(this->blocks),blocks,sizeof(rawChunkData));
	};
	rawSegment::rawSegment(const struct segmentHead *head,const chunkData*) {}; //TODO #15
	rawSegment::rawSegment(const struct segmentHead *head,const compressedChunkData*) {}; //TODO #16
	rawSegment::rawSegment(const struct segment *src) {}; //TODO #15
	rawSegment::rawSegment(const struct compressedSegment *src) {}; //TODO #16
	rawSegment::rawSegment(const rawCompressedSegment *src) {}; //TODO #17
	rawCompressedSegment *rawSegment::toRawCompressed(rawCompressedSegment *trg,const bool offset) {}; //TODO #18

	compressedSegment::compressedSegment(const struct compressedSegment *copy) {
		memcpy(this,copy,sizeof(struct compressedSegment));
	};
	compressedSegment::compressedSegment(const struct segmentHead *head,const compressedChunkData *blocks) {
		this->head=*head;
		memcpy(&(this->blocks),blocks,sizeof(compressedChunkData));
	};
	compressedSegment::compressedSegment(const struct segmentHead *head,const chunkData *blocks) {}; //TODO #21
	compressedSegment::compressedSegment(const struct segmentHead *head,const rawChunkData *blocks) {}; //TODO #22
	compressedSegment::compressedSegment(const struct segment *src) {}; //TODO #21
	compressedSegment::compressedSegment(const struct rawSegment *src) {}; //TODO #22
	compressedSegment::compressedSegment(const rawCompressedSegment *src) {}; //TODO #23
	rawCompressedSegment *compressedSegment::toRawCompressed(rawCompressedSegment *trg,const bool offset) {}; //TODO #24

	smd2Index::smd2Index(const struct smd2Index *copy) {
		this->id=copy->id;
		this->inlen=copy->inlen;
	};
	smd2Index::smd2Index(const signed long id, const unsigned long len) {
		this->id=id;
		this->inlen=len;
	};
	smd2Index::smd2Index() {
		this->id=-1;
		this->inlen=0;
	};
	smd2Index::smd2Index(const rawSmd2Index *raw) {
		uint32_t split[2];
		memcpy(split,raw,sizeof(rawSmd2Index));
		this->id=ntohl(split[0]);
		this->inlen=ntohl(split[1]);
	};
	rawSmd2Index *smd2Index::toRaw(rawSmd2Index *trg) {
		uint32_t split[2];
		split[0]=htonl(this->id);
		split[1]=htonl(this->inlen);
		memcpy(trg,split,sizeof(rawSmd2Index));
		return trg;
	};
	bool smd2Index::isValid() {
		return this->id!=-1;
	};

	smd2Head::smd2Head(const struct smd2Head*) {}; //TODO #25
	smd2Head::smd2Head(const unsigned long version, const fullSmd2Index *index,const fullSmd2TimestampHead *timestamps) {
		this->version=version;
		memcpy(&(this->index),index,sizeof(fullSmd2Index));
		memcpy(&(this->timestamps),timestamps,sizeof(fullSmd2TimestampHead));
	};
	smd2Head::smd2Head(const rawSmd2Head*) {}; //TODO #26
	rawSmd2Head *smd2Head::toRaw(rawSmd2Head*) {}; //TODO #27

	unsigned int getSegmentSlotCountFromSMD2Size(const size_t) {}; //TODO #29
	size_t getSMD2SizeFromSegmentSlotCount(const unsigned int) {}; //TODO #30
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 Kolibre
 *
 * This file is part of kolibre-clientcore.
 *
 * Kolibre-clientcore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Kolibre-clientcore 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with kolibre-clientcore. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Db.h"

#ifdef WIN32
#include <iconv.h>
#include <windows.h>
#endif

#include <cstdlib>
#include <unistd.h>
#include <cstdio>
#include <log4cxx/logger.h>

// create logger which will become a child to logger kolibre.clientcore
log4cxx::LoggerPtr dbLog(log4cxx::Logger::getLogger("kolibre.clientcore.db"));

using namespace std;

int busyHandler(void *pArg1, int iPriorCalls)
{
    LOG4CXX_WARN(dbLog, "busyHandler " << iPriorCalls << " !!");
    // sleep if handler has been called less than threshold value
    if (iPriorCalls < 20)
    {
        // adding a random value here greatly reduces locking
        if (pArg1 < 0)
            usleep((rand() % 500000) + 400000);
        else
            usleep(500000);
        return 1;
    }

    // have sqlite3_exec immediately return SQLITE_BUSY
    return 0;
}

DB::DB(const string &database)
{
    mDatabase = database;
    pDBHandle = NULL;
    pStatement = NULL;
    mLasterror = "";

}

DB::DB(sqlite3 *handle)
{
    pStatement = NULL;
    pDBHandle = handle;
    int sleepMode = 1;
    sqlite3_busy_handler(pDBHandle, &busyHandler, &sleepMode);
}

bool DB::connect()
{
    if (pDBHandle != NULL)
        return true;

    LOG4CXX_DEBUG(dbLog, "Opening settings database: " << mDatabase);
    if (sqlite3_open_v2(mDatabase.c_str(), &pDBHandle, SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        sqlite3_close(pDBHandle);
        pDBHandle = NULL;
        return false;
    }

    int sleepMode = 1;
    sqlite3_busy_handler(pDBHandle, &busyHandler, &sleepMode);

    bClosedb = true;
    return true;
}

DB::~DB()
{
    // If we recieved the handle in the constructor the caller should close the db
    if (pDBHandle && bClosedb)
    {
        sqlite3_close(pDBHandle);
    }
}

bool DB::prepare(const char *query)
{
    if (!pDBHandle)
        return false;
    if (pStatement)
        sqlite3_finalize(pStatement);

    if (query == NULL)
        query = mLastquery.c_str();

    pStatement = NULL;
    rc = sqlite3_prepare_v2(pDBHandle, query, -1, &pStatement, 0);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }

    mLastquery.assign(query);
    return true;
}

bool DB::bind(const int idx, const int value)
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_int(pStatement, idx, value);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const int value)
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value);
}

bool DB::bind(const int idx, const long value)
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_int(pStatement, idx, value);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const long value)
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value);
}

bool DB::bind(const int idx, const double value)
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_double(pStatement, idx, value);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const double value)
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value);
}

bool DB::bind(const int idx, const char *value, int length, void (*freefunc)(void*))
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_text(pStatement, idx, value, length, freefunc);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const char *value, int length, void (*freefunc)(void*))
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value, length, freefunc);
}

bool DB::bind(const int idx, const void *value, int length, void (*freefunc)(void*))
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_blob(pStatement, idx, value, length, freefunc);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const void *value, int length, void (*freefunc)(void*))
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value, length, freefunc);
}

bool DB::reset()
{
    if (pStatement)
    {
        rc = sqlite3_reset(pStatement);
        if (rc != SQLITE_OK)
        {
            mLasterror.assign(sqlite3_errmsg(pDBHandle));
            return false;
        }
    }
    // Prepares a copy of the previous query
    return prepare(NULL);
}

bool DB::perform(DBResult *result)
{
    if (!pStatement)
        return false;

    // Called does not want a result, only success or failure
    if (result == NULL)
    {
        DBResult res;
        res.setup(pDBHandle, pStatement);
        pStatement = NULL;
        while (!res.isError() && !res.isDone() && res.loadRow());
        bool ret = (!res.isError() && res.isDone());

        //printf("in perform, result NULL, returning %i, err %i, done %i\n", ret, res.isError(), res.isDone());

        return ret;
    }

    // return a result
    bool ret = result->setup(pDBHandle, pStatement);
    pStatement = NULL;
    return ret;
}

DBResult::DBResult()
{
    pDBHandle = NULL;
    pStatement = NULL;
}

bool DBResult::setup(sqlite3 *handle, sqlite3_stmt* statement)
{
    pDBHandle = handle;
    pStatement = statement;
    bFirstcall = true;
    bError = false;
    bDone = false;

    // Step once
    step();

    return !bError;
}

DBResult::~DBResult()
{
    if (pStatement)
    {
        sqlite3_finalize(pStatement);
    }
}

int DBResult::step()
{
    rc = sqlite3_step(pStatement);
    switch (rc)
    {
    case SQLITE_OK:
        //printf("Got ok\n");
        return rc;
        break;

    case SQLITE_ROW:
        //printf("Got row\n");
        return rc;

    case SQLITE_DONE:
        bDone = true;
        //printf("Got done\n");
        return 0;

    case SQLITE_CONSTRAINT:
        //printf("Got constraint violation\n");
        bError = true;
        mLasterror.assign("DB: SQLITE_CONSTRAINT violation");
        return rc;
        break;

    case SQLITE_MISUSE:
        bError = true;
        mLasterror.assign("DB: SQLITE_MISUSE");
        return rc;
        break;

    default:
        //printf("DB: error code: %d\n", rc);
        bError = true;
        mLasterror = sqlite3_errmsg(pDBHandle);
    }
    return rc;
}

bool DBResult::isError()
{
    return bError;
}

bool DBResult::isDone()
{
    return bDone;
}

bool DBResult::loadRow()
{
    if (bDone)
        return false;
    if (bError)
        return false;
    if (bFirstcall)
    {
        bFirstcall = false;
        if (rc == SQLITE_ROW)
            return true;
        return false;
    }

    if (step() == SQLITE_ROW)
        return true;
    return false;
}

void DBResult::printRow()
{
    int i;
    for (i = 0; i < sqlite3_column_count(pStatement); ++i)
        switch (sqlite3_column_type(pStatement, i))
        {
        case SQLITE_INTEGER:
            printf("%d\t", sqlite3_column_int(pStatement, i));
            break;
        case SQLITE_FLOAT:
            printf("%f\t", sqlite3_column_double(pStatement, i));
            break;
        case SQLITE_TEXT:
            printf("%s\t", sqlite3_column_text(pStatement, i));
            break;
        case SQLITE_BLOB:
            printf("<blob>%X\t", sqlite3_column_blob(pStatement, i));
            break;
        case SQLITE_NULL:
            printf("Null ");
            break;
        default:
            printf(" *Cannot determine SQLITE TYPE* col=%d ", i);
        }
    printf("\n");
}

long DBResult::getInsertId()
{
    return sqlite3_last_insert_rowid(pDBHandle);
}

long DBResult::getInt(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_INTEGER)
        return sqlite3_column_int(pStatement, column);

    return 0;
}

double DBResult::getDouble(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_FLOAT)
        return sqlite3_column_double(pStatement, column);

    return 0;
}

const char *DBResult::getText(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_TEXT)
        return (const char *) sqlite3_column_text(pStatement, column);

    return NULL;
}

const void *DBResult::getData(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_BLOB)
        return sqlite3_column_blob(pStatement, column);

    return NULL;
}

long DBResult::getDataSize(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_TEXT || sqlite3_column_type(pStatement, column) == SQLITE_BLOB)
        return sqlite3_column_bytes(pStatement, column);

    return 0;
}

<commit_msg>Db: initiate all variables on start<commit_after>/*
 * Copyright (C) 2012 Kolibre
 *
 * This file is part of kolibre-clientcore.
 *
 * Kolibre-clientcore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Kolibre-clientcore 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with kolibre-clientcore. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Db.h"

#ifdef WIN32
#include <iconv.h>
#include <windows.h>
#endif

#include <cstdlib>
#include <unistd.h>
#include <cstdio>
#include <log4cxx/logger.h>

// create logger which will become a child to logger kolibre.clientcore
log4cxx::LoggerPtr dbLog(log4cxx::Logger::getLogger("kolibre.clientcore.db"));

using namespace std;

int busyHandler(void *pArg1, int iPriorCalls)
{
    LOG4CXX_WARN(dbLog, "busyHandler " << iPriorCalls << " !!");
    // sleep if handler has been called less than threshold value
    if (iPriorCalls < 20)
    {
        // adding a random value here greatly reduces locking
        if (pArg1 < 0)
            usleep((rand() % 500000) + 400000);
        else
            usleep(500000);
        return 1;
    }

    // have sqlite3_exec immediately return SQLITE_BUSY
    return 0;
}

DB::DB(const string &database):
    mDatabase(database), pDBHandle(NULL), pStatement(NULL), mLasterror(""), mLastquery("")
{

}

DB::DB(sqlite3 *handle)
{
    pStatement = NULL;
    pDBHandle = handle;
    int sleepMode = 1;
    sqlite3_busy_handler(pDBHandle, &busyHandler, &sleepMode);
}

bool DB::connect()
{
    if (pDBHandle != NULL)
        return true;

    LOG4CXX_DEBUG(dbLog, "Opening settings database: " << mDatabase);
    if (sqlite3_open_v2(mDatabase.c_str(), &pDBHandle, SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        sqlite3_close(pDBHandle);
        pDBHandle = NULL;
        return false;
    }

    int sleepMode = 1;
    sqlite3_busy_handler(pDBHandle, &busyHandler, &sleepMode);

    bClosedb = true;
    return true;
}

DB::~DB()
{
    // If we recieved the handle in the constructor the caller should close the db
    if (pDBHandle && bClosedb)
    {
        sqlite3_close(pDBHandle);
    }
}

bool DB::prepare(const char *query)
{
    if (!pDBHandle)
        return false;
    if (pStatement)
        sqlite3_finalize(pStatement);

    if (query == NULL)
        query = mLastquery.c_str();

    pStatement = NULL;
    rc = sqlite3_prepare_v2(pDBHandle, query, -1, &pStatement, 0);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }

    mLastquery.assign(query);
    return true;
}

bool DB::bind(const int idx, const int value)
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_int(pStatement, idx, value);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const int value)
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value);
}

bool DB::bind(const int idx, const long value)
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_int(pStatement, idx, value);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const long value)
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value);
}

bool DB::bind(const int idx, const double value)
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_double(pStatement, idx, value);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const double value)
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value);
}

bool DB::bind(const int idx, const char *value, int length, void (*freefunc)(void*))
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_text(pStatement, idx, value, length, freefunc);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const char *value, int length, void (*freefunc)(void*))
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value, length, freefunc);
}

bool DB::bind(const int idx, const void *value, int length, void (*freefunc)(void*))
{
    if (!pStatement)
        prepare(NULL);
    if (idx == 0)
        return false;
    rc = sqlite3_bind_blob(pStatement, idx, value, length, freefunc);
    if (rc != SQLITE_OK)
    {
        mLasterror.assign(sqlite3_errmsg(pDBHandle));
        return false;
    }
    return true;
}

bool DB::bind(const char *key, const void *value, int length, void (*freefunc)(void*))
{
    return bind(sqlite3_bind_parameter_index(pStatement, key), value, length, freefunc);
}

bool DB::reset()
{
    if (pStatement)
    {
        rc = sqlite3_reset(pStatement);
        if (rc != SQLITE_OK)
        {
            mLasterror.assign(sqlite3_errmsg(pDBHandle));
            return false;
        }
    }
    // Prepares a copy of the previous query
    return prepare(NULL);
}

bool DB::perform(DBResult *result)
{
    if (!pStatement)
        return false;

    // Called does not want a result, only success or failure
    if (result == NULL)
    {
        DBResult res;
        res.setup(pDBHandle, pStatement);
        pStatement = NULL;
        while (!res.isError() && !res.isDone() && res.loadRow());
        bool ret = (!res.isError() && res.isDone());

        //printf("in perform, result NULL, returning %i, err %i, done %i\n", ret, res.isError(), res.isDone());

        return ret;
    }

    // return a result
    bool ret = result->setup(pDBHandle, pStatement);
    pStatement = NULL;
    return ret;
}

DBResult::DBResult()
{
    pDBHandle = NULL;
    pStatement = NULL;
}

bool DBResult::setup(sqlite3 *handle, sqlite3_stmt* statement)
{
    pDBHandle = handle;
    pStatement = statement;
    bFirstcall = true;
    bError = false;
    bDone = false;

    // Step once
    step();

    return !bError;
}

DBResult::~DBResult()
{
    if (pStatement)
    {
        sqlite3_finalize(pStatement);
    }
}

int DBResult::step()
{
    rc = sqlite3_step(pStatement);
    switch (rc)
    {
    case SQLITE_OK:
        //printf("Got ok\n");
        return rc;
        break;

    case SQLITE_ROW:
        //printf("Got row\n");
        return rc;

    case SQLITE_DONE:
        bDone = true;
        //printf("Got done\n");
        return 0;

    case SQLITE_CONSTRAINT:
        //printf("Got constraint violation\n");
        bError = true;
        mLasterror.assign("DB: SQLITE_CONSTRAINT violation");
        return rc;
        break;

    case SQLITE_MISUSE:
        bError = true;
        mLasterror.assign("DB: SQLITE_MISUSE");
        return rc;
        break;

    default:
        //printf("DB: error code: %d\n", rc);
        bError = true;
        mLasterror = sqlite3_errmsg(pDBHandle);
    }
    return rc;
}

bool DBResult::isError()
{
    return bError;
}

bool DBResult::isDone()
{
    return bDone;
}

bool DBResult::loadRow()
{
    if (bDone)
        return false;
    if (bError)
        return false;
    if (bFirstcall)
    {
        bFirstcall = false;
        if (rc == SQLITE_ROW)
            return true;
        return false;
    }

    if (step() == SQLITE_ROW)
        return true;
    return false;
}

void DBResult::printRow()
{
    int i;
    for (i = 0; i < sqlite3_column_count(pStatement); ++i)
        switch (sqlite3_column_type(pStatement, i))
        {
        case SQLITE_INTEGER:
            printf("%d\t", sqlite3_column_int(pStatement, i));
            break;
        case SQLITE_FLOAT:
            printf("%f\t", sqlite3_column_double(pStatement, i));
            break;
        case SQLITE_TEXT:
            printf("%s\t", sqlite3_column_text(pStatement, i));
            break;
        case SQLITE_BLOB:
            printf("<blob>%X\t", sqlite3_column_blob(pStatement, i));
            break;
        case SQLITE_NULL:
            printf("Null ");
            break;
        default:
            printf(" *Cannot determine SQLITE TYPE* col=%d ", i);
        }
    printf("\n");
}

long DBResult::getInsertId()
{
    return sqlite3_last_insert_rowid(pDBHandle);
}

long DBResult::getInt(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_INTEGER)
        return sqlite3_column_int(pStatement, column);

    return 0;
}

double DBResult::getDouble(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_FLOAT)
        return sqlite3_column_double(pStatement, column);

    return 0;
}

const char *DBResult::getText(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_TEXT)
        return (const char *) sqlite3_column_text(pStatement, column);

    return NULL;
}

const void *DBResult::getData(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_BLOB)
        return sqlite3_column_blob(pStatement, column);

    return NULL;
}

long DBResult::getDataSize(const long column)
{
    if (sqlite3_column_type(pStatement, column) == SQLITE_TEXT || sqlite3_column_type(pStatement, column) == SQLITE_BLOB)
        return sqlite3_column_bytes(pStatement, column);

    return 0;
}

<|endoftext|>