<commit_before>#include <ghost.h>
#include <ghost_util.h>
#include <ghost_mat.h>
#include <crs.h>
#include "ghost_complex.h"
#include <iostream>
#include <omp.h>

// TODO shift, scale als templateparameter

template<typename m_t, typename v_t> void CRS_kernel_plain_tmpl(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{
//#pragma omp parallel
//	{
//	if (omp_get_thread_num() == (omp_get_num_threads()-1)) {
	//	WARNING_LOG("Thread %d/%d running @ core %d",omp_get_thread_num(),omp_get_num_threads()-1,ghost_getCore());
//	}
//	}
	CR_TYPE *cr = CR(mat);
	v_t *rhsv = (v_t *)(rhs->val);
	v_t *lhsv = (v_t *)(lhs->val);
	m_t *mval = (m_t *)(cr->val);
	ghost_midx_t i, j;
	v_t hlp1 = 0.;
	v_t shift, scale;
	if (options & GHOST_SPMVM_APPLY_SHIFT)
		shift = *((v_t *)(mat->traits->shift));
	if (options & GHOST_SPMVM_APPLY_SCALE)
		scale = *((v_t *)(mat->traits->scale));

#pragma omp parallel for schedule(runtime) private (hlp1, j)
	for (i=0; i<cr->nrows; i++){
		hlp1 = (v_t)0.0;
		for (j=cr->rpt[i]; j<cr->rpt[i+1]; j++){
			hlp1 += ((v_t)(mval[j])) * rhsv[cr->col[j]];
		}

		if (options & GHOST_SPMVM_APPLY_SHIFT) {
			if (options & GHOST_SPMVM_APPLY_SCALE) {
				if (options & GHOST_SPMVM_AXPY) {
					lhsv[i] += scale*(hlp1+shift*rhsv[i]);
				} else {
					lhsv[i] = scale*(hlp1+shift*rhsv[i]);
				}
			} else {
				if (options & GHOST_SPMVM_AXPY) {
					lhsv[i] += (hlp1+shift*rhsv[i]);
				} else {
					lhsv[i] = (hlp1+shift*rhsv[i]);
				}
			}
		} else {
			if (options & GHOST_SPMVM_APPLY_SCALE) {
				if (options & GHOST_SPMVM_AXPY) {
					lhsv[i] += scale*(hlp1);
				} else {
					lhsv[i] = scale*(hlp1);
				}
			} else {
				if (options & GHOST_SPMVM_AXPY) {
					lhsv[i] += (hlp1);
				} else {
					lhsv[i] = (hlp1);
				}
			}

		}
	}
}

template<typename m_t, typename f_t> void CRS_castData_tmpl(void *matrixData, void *fileData, int nEnts)
{
	ghost_mnnz_t i;
	m_t *md = (m_t *)matrixData;
	f_t *fd = (f_t *)fileData;

	for (i = 0; i<nEnts; i++) {
		md[i] = (m_t)(fd[i]);
	}
}

template<typename m_t> void CRS_valToStr_tmpl(void *val, char *str, int n)
{
	if (val == NULL) {
		UNUSED(str);
		//str = "0.";
	} else {
		UNUSED(str);
		UNUSED(n);
		// TODO
		//snprintf(str,n,"%g",*((m_t *)(val)));
	}
}

extern "C" void dd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,double >(mat,lhs,rhs,options); }

extern "C" void ds_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,float >(mat,lhs,rhs,options); }

extern "C" void dc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void dz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void sd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,double >(mat,lhs,rhs,options); }

extern "C" void ss_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,float >(mat,lhs,rhs,options); }

extern "C" void sc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void sz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void cd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,double >(mat,lhs,rhs,options); }

extern "C" void cs_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,float >(mat,lhs,rhs,options); }

extern "C" void cc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void cz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void zd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,double >(mat,lhs,rhs,options); }

extern "C" void zs_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,float >(mat,lhs,rhs,options); }

extern "C" void zc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void zz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void dd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,double >(matrixData, fileData, nEnts); }

extern "C" void ds_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,float >(matrixData, fileData, nEnts); }

extern "C" void dc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void dz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void sd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,double >(matrixData, fileData, nEnts); }

extern "C" void ss_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,float >(matrixData, fileData, nEnts); }

extern "C" void sc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void sz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void cd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,double >(matrixData, fileData, nEnts); }

extern "C" void cs_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,float >(matrixData, fileData, nEnts); }

extern "C" void cc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void cz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void zd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,double >(matrixData, fileData, nEnts); }

extern "C" void zs_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,float >(matrixData, fileData, nEnts); }

extern "C" void zc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void zz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void d_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< double >(val,str,n); }

extern "C" void s_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< float >(val,str,n); }

extern "C" void c_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< ghost_complex<float> >(val,str,n); }

extern "C" void z_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< ghost_complex<double> >(val,str,n); }
<commit_msg>CRS spMVM kernel now multi-vector aware (untested)<commit_after>#include <ghost.h>
#include <ghost_util.h>
#include <ghost_mat.h>
#include <crs.h>
#include "ghost_complex.h"
#include <iostream>
#include <omp.h>

// TODO shift, scale als templateparameter

template<typename m_t, typename v_t> void CRS_kernel_plain_tmpl(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{
	CR_TYPE *cr = CR(mat);
	v_t *rhsv = (v_t *)(rhs->val);
	v_t *lhsv = (v_t *)(lhs->val);
	m_t *mval = (m_t *)(cr->val);
	ghost_midx_t i, j;
	ghost_vidx_t v;

	v_t hlp1 = 0.;
	v_t shift, scale;
	if (options & GHOST_SPMVM_APPLY_SHIFT)
		shift = *((v_t *)(mat->traits->shift));
	if (options & GHOST_SPMVM_APPLY_SCALE)
		scale = *((v_t *)(mat->traits->scale));

	for (v=0; v<MIN(lhs->traits->nvecs,rhs->traits->nvecs); v++)
	{
#pragma omp parallel for schedule(runtime) private (hlp1, j)
		for (i=0; i<cr->nrows; i++){
			hlp1 = (v_t)0.0;
			for (j=cr->rpt[i]; j<cr->rpt[i+1]; j++){
				hlp1 += ((v_t)(mval[j])) * rhsv[v*rhs->traits->nrowspadded+cr->col[j]];
			}

			if (options & GHOST_SPMVM_APPLY_SHIFT) {
				if (options & GHOST_SPMVM_APPLY_SCALE) {
					if (options & GHOST_SPMVM_AXPY) {
						lhsv[v*lhs->traits->nrowspadded+i] += scale*(hlp1+shift*rhsv[v*rhs->traits->nrowspadded+i]);
					} else {
						lhsv[v*lhs->traits->nrowspadded+i] = scale*(hlp1+shift*rhsv[v*rhs->traits->nrowspadded+i]);
					}
				} else {
					if (options & GHOST_SPMVM_AXPY) {
						lhsv[v*lhs->traits->nrowspadded+i] += (hlp1+shift*rhsv[v*rhs->traits->nrowspadded+i]);
					} else {
						lhsv[v*lhs->traits->nrowspadded+i] = (hlp1+shift*rhsv[v*rhs->traits->nrowspadded+i]);
					}
				}
			} else {
				if (options & GHOST_SPMVM_APPLY_SCALE) {
					if (options & GHOST_SPMVM_AXPY) {
						lhsv[v*lhs->traits->nrowspadded+i] += scale*(hlp1);
					} else {
						lhsv[v*lhs->traits->nrowspadded+i] = scale*(hlp1);
					}
				} else {
					if (options & GHOST_SPMVM_AXPY) {
						lhsv[v*lhs->traits->nrowspadded+i] += (hlp1);
					} else {
						lhsv[v*lhs->traits->nrowspadded+i] = (hlp1);
					}
				}

			}
		}
	}
}

template<typename m_t, typename f_t> void CRS_castData_tmpl(void *matrixData, void *fileData, int nEnts)
{
	ghost_mnnz_t i;
	m_t *md = (m_t *)matrixData;
	f_t *fd = (f_t *)fileData;

	for (i = 0; i<nEnts; i++) {
		md[i] = (m_t)(fd[i]);
	}
}

template<typename m_t> void CRS_valToStr_tmpl(void *val, char *str, int n)
{
	if (val == NULL) {
		UNUSED(str);
		//str = "0.";
	} else {
		UNUSED(str);
		UNUSED(n);
		// TODO
		//snprintf(str,n,"%g",*((m_t *)(val)));
	}
}

extern "C" void dd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,double >(mat,lhs,rhs,options); }

extern "C" void ds_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,float >(mat,lhs,rhs,options); }

extern "C" void dc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void dz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< double,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void sd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,double >(mat,lhs,rhs,options); }

extern "C" void ss_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,float >(mat,lhs,rhs,options); }

extern "C" void sc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void sz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< float,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void cd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,double >(mat,lhs,rhs,options); }

extern "C" void cs_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,float >(mat,lhs,rhs,options); }

extern "C" void cc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void cz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<float>,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void zd_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,double >(mat,lhs,rhs,options); }

extern "C" void zs_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,float >(mat,lhs,rhs,options); }

extern "C" void zc_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,ghost_complex<float> >(mat,lhs,rhs,options); }

extern "C" void zz_CRS_kernel_plain(ghost_mat_t *mat, ghost_vec_t *lhs, ghost_vec_t *rhs, int options)
{ return CRS_kernel_plain_tmpl< ghost_complex<double>,ghost_complex<double> >(mat,lhs,rhs,options); }

extern "C" void dd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,double >(matrixData, fileData, nEnts); }

extern "C" void ds_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,float >(matrixData, fileData, nEnts); }

extern "C" void dc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void dz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< double,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void sd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,double >(matrixData, fileData, nEnts); }

extern "C" void ss_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,float >(matrixData, fileData, nEnts); }

extern "C" void sc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void sz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< float,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void cd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,double >(matrixData, fileData, nEnts); }

extern "C" void cs_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,float >(matrixData, fileData, nEnts); }

extern "C" void cc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void cz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<float>,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void zd_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,double >(matrixData, fileData, nEnts); }

extern "C" void zs_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,float >(matrixData, fileData, nEnts); }

extern "C" void zc_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,ghost_complex<float> >(matrixData, fileData, nEnts); }

extern "C" void zz_CRS_castData(void *matrixData, void *fileData, int nEnts)
{ return CRS_castData_tmpl< ghost_complex<double>,ghost_complex<double> >(matrixData, fileData, nEnts); }

extern "C" void d_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< double >(val,str,n); }

extern "C" void s_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< float >(val,str,n); }

extern "C" void c_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< ghost_complex<float> >(val,str,n); }

extern "C" void z_CRS_valToStr(void *val, char *str, int n)
{ return CRS_valToStr_tmpl< ghost_complex<double> >(val,str,n); }
<|endoftext|>


<commit_before>// Copyright 2015-2018 Kuzzle
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 		http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "kuzzle.hpp"
#include "auth.hpp"

namespace kuzzleio {
  Auth::Auth(Kuzzle *kuzzle) {
      _auth = new auth();
      _kuzzle = kuzzle;
      kuzzle_new_auth(_auth, kuzzle->_kuzzle);
  }

  Auth::Auth(Kuzzle *kuzzle, auth *auth) {
    _auth = auth;
    _kuzzle = kuzzle;
    kuzzle_new_auth(_auth, kuzzle->_kuzzle);
  }

  Auth::~Auth() {
      unregisterAuth(_auth);
      delete(_auth);
  }

  token_validity* Auth::checkToken(const std::string& token) {
    return kuzzle_check_token(_auth, const_cast<char*>(token.c_str()));
  }

  std::string Auth::createMyCredentials(const std::string& strategy, const std::string& credentials, query_options* options) {
    string_result* r = kuzzle_create_my_credentials(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), options);
    if (r->error)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    delete(r);
    return ret;
  }

  bool Auth::credentialsExist(const std::string& strategy, query_options *options) {
    bool_result* r = kuzzle_credentials_exist(_auth, const_cast<char*>(strategy.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    bool ret = r->result;
    delete(r);
    return ret;
  }

  void Auth::deleteMyCredentials(const std::string& strategy, query_options *options) {
    error_result *r = kuzzle_delete_my_credentials(_auth, const_cast<char*>(strategy.c_str()), options);
    if (r != nullptr)
        throwExceptionFromStatus(r);
    delete(r);
  }

  kuzzle_user* Auth::getCurrentUser() {
    user_result *r = kuzzle_get_current_user(_auth);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);

    kuzzle_user *u = r->result;
    kuzzle_free_user_result(r);
    return u;
  }

  std::string Auth::getMyCredentials(const std::string& strategy, query_options *options) {
    string_result *r = kuzzle_get_my_credentials(_auth, const_cast<char*>(strategy.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  user_right* Auth::getMyRights(query_options* options) {
    user_rights_result *r = kuzzle_get_my_rights(_auth, options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    user_right *ret = r->result;
    kuzzle_free_user_rights_result(r);
    return ret;
  }

  std::vector<std::string> Auth::getStrategies(query_options *options) {
    string_array_result *r = kuzzle_get_strategies(_auth, options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);

    std::vector<std::string> v;
    for (int i = 0; r->result[i]; i++)
        v.push_back(r->result[i]);

    kuzzle_free_string_array_result(r);
    return v;
  }

  std::string Auth::login(const std::string& strategy, const std::string& credentials) {
    string_result* r = kuzzle_login(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), nullptr);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  std::string Auth::login(const std::string& strategy, const std::string& credentials, int expires_in) {
    string_result* r = kuzzle_login(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), &expires_in);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  void Auth::logout() noexcept {
    kuzzle_logout(_auth);
  }

  void Auth::setJwt(const std::string& jwt) {
    kuzzle_set_jwt(_kuzzle->_kuzzle, const_cast<char*>(jwt.c_str()));
  }

  std::string Auth::updateMyCredentials(const std::string& strategy, const std::string& credentials, query_options *options) {
    string_result *r = kuzzle_update_my_credentials(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  kuzzle_user* Auth::updateSelf(const std::string& content, query_options* options) {
    user_result *r = kuzzle_update_self(_auth, const_cast<char*>(content.c_str()), options);
    if (r->error != nullptr)
      throwExceptionFromStatus(r);
    kuzzle_user *ret = r->result;
    kuzzle_free_user_result(r);
    return ret;
  }

  bool Auth::validateMyCredentials(const std::string& strategy, const std::string& credentials, query_options* options) {
    bool_result *r = kuzzle_validate_my_credentials(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    bool ret = r->result;
    kuzzle_free_bool_result(r);
    return ret;
  }

}
<commit_msg>fix signatures<commit_after>// Copyright 2015-2018 Kuzzle
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 		http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "kuzzle.hpp"
#include "auth.hpp"

namespace kuzzleio {
  Auth::Auth(Kuzzle *kuzzle) {
      _auth = new auth();
      _kuzzle = kuzzle;
      kuzzle_new_auth(_auth, kuzzle->_kuzzle);
  }

  Auth::Auth(Kuzzle *kuzzle, auth *auth) {
    _auth = auth;
    _kuzzle = kuzzle;
    kuzzle_new_auth(_auth, kuzzle->_kuzzle);
  }

  Auth::~Auth() {
      unregisterAuth(_auth);
      delete(_auth);
  }

  token_validity* Auth::checkToken(const std::string& token) {
    return kuzzle_check_token(_auth, const_cast<char*>(token.c_str()));
  }

  std::string Auth::createMyCredentials(const std::string& strategy, const std::string& credentials, query_options* options) {
    string_result* r = kuzzle_create_my_credentials(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), options);
    if (r->error)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    delete(r);
    return ret;
  }

  bool Auth::credentialsExist(const std::string& strategy, query_options *options) {
    bool_result* r = kuzzle_credentials_exist(_auth, const_cast<char*>(strategy.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    bool ret = r->result;
    delete(r);
    return ret;
  }

  void Auth::deleteMyCredentials(const std::string& strategy, query_options *options) {
    error_result *r = kuzzle_delete_my_credentials(_auth, const_cast<char*>(strategy.c_str()), options);
    if (r != nullptr)
        throwExceptionFromStatus(r);
    delete(r);
  }

  kuzzle_user* Auth::getCurrentUser() {
    user_result *r = kuzzle_get_current_user(_auth);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);

    kuzzle_user *u = r->result;
    kuzzle_free_user_result(r);
    return u;
  }

  std::string Auth::getMyCredentials(const std::string& strategy, query_options *options) {
    string_result *r = kuzzle_get_my_credentials(_auth, const_cast<char*>(strategy.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  user_right* Auth::getMyRights(query_options* options) {
    user_rights_result *r = kuzzle_get_my_rights(_auth, options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    user_right *ret = r->result;
    kuzzle_free_user_rights_result(r);
    return ret;
  }

  std::vector<std::string> Auth::getStrategies(query_options *options) {
    string_array_result *r = kuzzle_get_strategies(_auth, options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);

    std::vector<std::string> v;
    for (int i = 0; r->result[i]; i++)
        v.push_back(r->result[i]);

    kuzzle_free_string_array_result(r);
    return v;
  }

  std::string Auth::login(const std::string& strategy, const std::string& credentials) {
    string_result* r = kuzzle_login(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), nullptr);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  std::string Auth::login(const std::string& strategy, const std::string& credentials, int expires_in) {
    string_result* r = kuzzle_login(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), &expires_in);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  void Auth::logout() noexcept {
    kuzzle_logout(_auth);
  }

  void Auth::setJwt(const std::string& jwt) noexcept {
    kuzzle_set_jwt(_kuzzle->_kuzzle, const_cast<char*>(jwt.c_str()));
  }

  std::string Auth::updateMyCredentials(const std::string& strategy, const std::string& credentials, query_options *options) {
    string_result *r = kuzzle_update_my_credentials(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    std::string ret = r->result;
    kuzzle_free_string_result(r);
    return ret;
  }

  kuzzle_user* Auth::updateSelf(const std::string& content, query_options* options) {
    user_result *r = kuzzle_update_self(_auth, const_cast<char*>(content.c_str()), options);
    if (r->error != nullptr)
      throwExceptionFromStatus(r);
    kuzzle_user *ret = r->result;
    kuzzle_free_user_result(r);
    return ret;
  }

  bool Auth::validateMyCredentials(const std::string& strategy, const std::string& credentials, query_options* options) {
    bool_result *r = kuzzle_validate_my_credentials(_auth, const_cast<char*>(strategy.c_str()), const_cast<char*>(credentials.c_str()), options);
    if (r->error != nullptr)
        throwExceptionFromStatus(r);
    bool ret = r->result;
    kuzzle_free_bool_result(r);
    return ret;
  }

}
<|endoftext|>


<commit_before>//
//  16bitBinaryLoader.cpp
//  Phantasma
//
//  Created by Thomas Harte on 17/12/2013.
//  Copyright (c) 2013 Thomas Harte. All rights reserved.
//

#include "16bitBinaryLoader.h"

#include "Parser.h"
#include "16bitDetokeniser.h"

#include "Object.h"
#include "Area.h"

#include <map>

class StreamLoader
{
	private:
		vector<uint8_t>::size_type bytePointer;
		vector <uint8_t> binary;
		uint8_t readMaskByte1;
		uint8_t readMaskByte2;

	public:
		StreamLoader(vector <uint8_t> &_binary)
		{
			binary = _binary;
			bytePointer = 0;
			readMaskByte1 = 0;
			readMaskByte2 = 0;
		}

		uint8_t get8()
		{
			if(!eof())
			{
				uint8_t sourceByte = binary[bytePointer];

				if(bytePointer&1)
					sourceByte ^= readMaskByte2;
				else
					sourceByte ^= readMaskByte1;

				bytePointer++;
				return sourceByte;
			}

			return 0;
		}

		uint16_t get16()
		{
			uint16_t result = (uint16_t)(get8() << 8);
			result |= get8();
			return result;
		}

		uint32_t get32()
		{
			uint32_t result = (uint32_t)(get16() << 16);
			result |= get16();
			return result;
		}

		bool eof()
		{
			return bytePointer >= binary.size();
		}

		void alignPointer()
		{
			if(bytePointer&1) bytePointer++;
		}

		void skipBytes(vector<uint8_t>::size_type numberOfBytes)
		{
			bytePointer += numberOfBytes;
		}

		shared_ptr<vector<uint8_t>> nextBytes(vector<uint8_t>::size_type numberOfBytes)
		{
			shared_ptr<vector<uint8_t>> returnBuffer(new vector<uint8_t>);

			while(numberOfBytes--)
				returnBuffer->push_back(get8());

			return returnBuffer;
		}

		vector<uint8_t>::size_type getFileOffset()
		{
			return bytePointer;
		}

		void setFileOffset(vector<uint8_t>::size_type newOffset)
		{
			bytePointer = newOffset;
		}

		void setReadMask(uint8_t byte1, uint8_t byte2)
		{
			readMaskByte1 = byte1;
			readMaskByte2 = byte2;
		}
};

static Object *loadObject(StreamLoader &stream)
{
	// get object flags and type
	uint8_t objectFlags = stream.get8();
	Object::Type objectType = (Object::Type)stream.get8();

	// get unknown value
	uint16_t skippedShort = stream.get16();

	// grab location, size
	Vector3d position, size;
	position.x		= stream.get16();
	position.y		= stream.get16();
	position.z		= stream.get16();
	size.x			= stream.get16();
	size.y			= stream.get16();
	size.z			= stream.get16();

	// object ID
	uint16_t objectID = stream.get16();

	// size of object on disk; we've accounted for 20 bytes
	// already so we can subtract that to get the remaining
	// length beyond here
	uint32_t byteSizeOfObject = (uint32_t)(stream.get16() << 1) - 20;

	std::cout << "Object " << objectID << "; type " << (int)objectType << std::endl;

	switch(objectType)
	{
		default:
		{
			// read the appropriate number of colours
			int numberOfColours = GeometricObject::numberOfColoursForObjectOfType(objectType);
			std::vector<uint8_t> *colours = new std::vector<uint8_t>;
			for(uint8_t colour = 0; colour < numberOfColours; colour++)
			{
				colours->push_back(stream.get8());
				byteSizeOfObject--;
			}

			// read extra vertices if required...
			int numberOfOrdinates = GeometricObject::numberOfOrdinatesForType(objectType);
			std::vector<uint16_t> *ordinates = nullptr;

			if(numberOfOrdinates)
			{
				ordinates = new std::vector<uint16_t>;

				for(int ordinate = 0; ordinate < numberOfOrdinates; ordinate++)
				{
					ordinates->push_back(stream.get16());
					byteSizeOfObject -= 2;
				}
			}

			// grab the object condition, if there is one
			FCLInstructionVector instructions;
			if(byteSizeOfObject)
			{
				shared_ptr<vector<uint8_t>> conditionData = stream.nextBytes(byteSizeOfObject);

				shared_ptr<string> conditionSource = detokenise16bitCondition(*conditionData);
				instructions = getInstructions(conditionSource.get());
			}
			byteSizeOfObject = 0;

			// create an object
			return
				new GeometricObject(
					objectType,
					objectID,
					position,
					size,
					colours,
					ordinates,
					instructions);
		}
		break;

		case Object::Entrance:
		case Object::Sensor:
		case Object::Group:
		break;
	}

	// skip whatever we didn't understand
	stream.skipBytes(byteSizeOfObject);

	return nullptr;
}

static shared_ptr<Area> loadArea(StreamLoader &stream)
{
	// the lowest bit of this value seems to indicate
	// horizon on or off; this is as much as I currently know
	uint16_t skippedValue		= stream.get16();
	uint16_t numberOfObjects	= stream.get16();
	uint16_t areaNumber			= stream.get16();

	cout << "Area " << areaNumber << endl;
	cout << "Skipped value " << skippedValue << endl;
	cout << "Objects: " << numberOfObjects << endl;

	// I've yet to decipher this fully
	uint16_t horizonColour	= stream.get16();
	cout << "Horizon colour " << hex << (int)horizonColour << dec << endl;

	// this is just a complete guess
	for(int paletteEntry = 0; paletteEntry < 22; paletteEntry++)
	{
		uint8_t paletteColour		= stream.get8();
		cout << "Palette colour (?) " << hex << (int)paletteColour << dec << endl;
	}

	// we'll need to collate all objects and entrances; it's likely a
	// plain C array would do but maps are safer and the total application
	// cost is going to be negligible regardless
	ObjectMap *objectsByID = new ObjectMap;
	ObjectMap *entrancesByID = new ObjectMap;

	// get the objects or whatever; entrances use a unique numbering
	// system and have the high bit of their IDs set in the original file
	for(uint16_t object = 0; object < numberOfObjects; object++)
	{
		Object *newObject = loadObject(stream);

		if(newObject)
		{
			if(newObject->getType() == Object::Entrance)
			{
				(*entrancesByID)[newObject->getObjectID() & 0x7fff] = newObject;
			}
			else
			{
				(*objectsByID)[newObject->getObjectID()] = newObject;
			}
		}
	}

	return shared_ptr<Area>(new Area(areaNumber, objectsByID, entrancesByID));
}

Game *load16bitBinary(vector <uint8_t> &binary)
{
	StreamLoader streamLoader(binary);

	vector<uint8_t>::size_type baseOffset = 0;

	// check whether this looks like an Amiga game; if so it'll start with AM
	// XOR'd with the repeating byte pattern 0x71, 0xc1 or with the pattern
	// 0x88 0x2c if it's on the ST (though the signature will still be AM)
	uint16_t platformID = streamLoader.get16();

	if(
		(platformID == 12428) || (platformID == 51553)
	)
	{
		// TODO: record original platform type, so we can decode the palette
		// and possibly the border properly

		streamLoader.setReadMask((platformID >> 8) ^ 'A', (platformID & 0xff) ^ 'M');
	}
	else
	{
		// find DOS end of file and consume it
		while(!streamLoader.eof() && streamLoader.get8() != 0x1a);
		streamLoader.get8();

		// advance to the next two-byte boundary if necessary
		streamLoader.alignPointer();

		// skip bytes with meaning unknown
		streamLoader.get16();

		// this brings us to the beginning of the embedded
		// .KIT file, so we'll grab the base offset for
		// finding areas later
		baseOffset = streamLoader.getFileOffset();

		// check that the next two bytes are "PC", then
		// skip the number that comes after
		if(streamLoader.get8() != 'C' || streamLoader.get8() != 'P') return nullptr;
	}

	// skip an unknown meaning
	streamLoader.get16();

	// start grabbing some of the basics...

	uint16_t numberOfAreas = streamLoader.get16();
	streamLoader.get16();							// meaning unknown

	cout << numberOfAreas << " Areas" << endl;

	uint16_t windowCentreX	= streamLoader.get16();
	uint16_t windowCentreY	= streamLoader.get16();
	uint16_t windowWidth	= streamLoader.get16();
	uint16_t windowHeight	= streamLoader.get16();

	cout << "Window centre: ("	<< windowCentreX	<< ", " << windowCentreY	<< ")" << endl;
	cout << "Window size: ("	<< windowWidth		<< ", " << windowHeight		<< ")" << endl;

	uint16_t scaleX	= streamLoader.get16();
	uint16_t scaleY	= streamLoader.get16();
	uint16_t scaleZ	= streamLoader.get16();

	cout << "Scale: " << scaleX << ", " << scaleY << ", " << scaleZ << endl;

	uint16_t timerReload	= streamLoader.get16();

	cout << "Timer: every " << timerReload << " 50Hz frames";

	uint16_t maximumActivationDistance	= streamLoader.get16();
	uint16_t maximumFallDistance		= streamLoader.get16();
	uint16_t maximumClimbDistance		= streamLoader.get16();

	cout << "Maximum activation distance: "		<< maximumActivationDistance << endl;
	cout << "Maximum fall distance: "			<< maximumFallDistance << endl;
	cout << "Maximum climb distance: "			<< maximumClimbDistance << endl;

	uint16_t startArea					= streamLoader.get16();
	uint16_t startEntrance				= streamLoader.get16();

	cout << "Start at entrance " << startEntrance << " in area " << startArea << endl;

	uint16_t playerHeight				= streamLoader.get16();
	uint16_t playerStep					= streamLoader.get16();
	uint16_t playerAngle				= streamLoader.get16();

	cout << "Height " << playerHeight << ", stap " << playerStep << ", angle " << playerAngle << endl;

	uint16_t startVehicle				= streamLoader.get16();
	uint16_t executeGlobalCondition		= streamLoader.get16();

	cout << "Start vehicle " << startVehicle << ", execute global condition " << executeGlobalCondition << endl;

	// I haven't figured out what the next 106
	// bytes mean, so we'll skip them — global objects
	// maybe? Likely not 106 bytes in every file.
	//
	// ADDED: having rediscovered my source for the 8bit
	// file format, could this be shading information by
	// analogy with that?
	streamLoader.skipBytes(106);

	// at this point I should properly load the border/key/mouse
	// bindings, but I'm not worried about it for now.
	//
	// Format is:
	//		(left x, top y, right x, bottom y) - all 16 bit
	//		keyboard key as an ASCII character (or zero for none)
	//		mouse button masl; 00 = both, 01 = left, 02 = right
	//
	// So, 10 bytes per binding. Bindings are listed in the order:
	//
	//	move forwards, move backwards, move right, move left, rise,
	//	fall, turn left, turn right, look up, look down, tilt left,
	//	tilt right, face forward, u-turn, change vehicle type,
	//	select this vehicle, quit game, fire, activate object,
	//	centre cursor on/off, save game position, load game position
	//
	// So 35 total. Which means this area takes up 350 bytes.
	streamLoader.skipBytes(350);

	// there are then file pointers for every area — these are
	// the number of shorts from the 'PC' tag, so multiply by
	// two for bytes. Each is four bytes
	uint32_t *fileOffsetForArea = new uint32_t[numberOfAreas];
	for(uint16_t area = 0; area < numberOfAreas; area++)
		fileOffsetForArea[area] = (uint32_t)streamLoader.get32() << 1;

	// now come the global conditions
	uint16_t numberOfGlobalConditions = streamLoader.get16();
	for(uint16_t globalCondition = 0; globalCondition < numberOfGlobalConditions; globalCondition++)
	{
		// 12 bytes for the name of the condition;
		// we don't care
		streamLoader.skipBytes(12);

		// get the length and the data itself, converting from
		// shorts to bytes
		uint32_t lengthOfCondition = (uint32_t)streamLoader.get16() << 1;

		// get the condition
		shared_ptr<vector<uint8_t>> conditionData = streamLoader.nextBytes(lengthOfCondition);

		cout << "Global condition " << globalCondition+1 << endl;
		cout << *detokenise16bitCondition(*conditionData) << endl;
	}

	// grab the areas
	AreaMap *areaMap = new AreaMap;
	for(uint16_t area = 0; area < numberOfAreas; area++)
	{
//		cout << "Area " << area+1 << endl;

		streamLoader.setFileOffset(fileOffsetForArea[area] + baseOffset);
		shared_ptr<Area> newArea = loadArea(streamLoader);

		if(newArea.get())
		{
			(*areaMap)[newArea->getAreaID()] = newArea;
		}

		cout << endl;
	}

	delete[] fileOffsetForArea;
	return new Game(areaMap);
}
<commit_msg>Either the encryptions are more random than I thought or I’ve stumbled upon an Amiga 3d Construction Kit 2 file. I’m not sure yet.<commit_after>//
//  16bitBinaryLoader.cpp
//  Phantasma
//
//  Created by Thomas Harte on 17/12/2013.
//  Copyright (c) 2013 Thomas Harte. All rights reserved.
//

#include "16bitBinaryLoader.h"

#include "Parser.h"
#include "16bitDetokeniser.h"

#include "Object.h"
#include "Area.h"

#include <map>

class StreamLoader
{
	private:
		vector<uint8_t>::size_type bytePointer;
		vector <uint8_t> binary;
		uint8_t readMaskByte1;
		uint8_t readMaskByte2;

	public:
		StreamLoader(vector <uint8_t> &_binary)
		{
			binary = _binary;
			bytePointer = 0;
			readMaskByte1 = 0;
			readMaskByte2 = 0;
		}

		uint8_t get8()
		{
			if(!eof())
			{
				uint8_t sourceByte = binary[bytePointer];

				if(bytePointer&1)
					sourceByte ^= readMaskByte2;
				else
					sourceByte ^= readMaskByte1;

				bytePointer++;
				return sourceByte;
			}

			return 0;
		}

		uint16_t get16()
		{
			uint16_t result = (uint16_t)(get8() << 8);
			result |= get8();
			return result;
		}

		uint32_t get32()
		{
			uint32_t result = (uint32_t)(get16() << 16);
			result |= get16();
			return result;
		}

		bool eof()
		{
			return bytePointer >= binary.size();
		}

		void alignPointer()
		{
			if(bytePointer&1) bytePointer++;
		}

		void skipBytes(vector<uint8_t>::size_type numberOfBytes)
		{
			bytePointer += numberOfBytes;
		}

		shared_ptr<vector<uint8_t>> nextBytes(vector<uint8_t>::size_type numberOfBytes)
		{
			shared_ptr<vector<uint8_t>> returnBuffer(new vector<uint8_t>);

			while(numberOfBytes--)
				returnBuffer->push_back(get8());

			return returnBuffer;
		}

		vector<uint8_t>::size_type getFileOffset()
		{
			return bytePointer;
		}

		void setFileOffset(vector<uint8_t>::size_type newOffset)
		{
			bytePointer = newOffset;
		}

		void setReadMask(uint8_t byte1, uint8_t byte2)
		{
			readMaskByte1 = byte1;
			readMaskByte2 = byte2;
		}
};

static Object *loadObject(StreamLoader &stream)
{
	// get object flags and type
	uint8_t objectFlags = stream.get8();
	Object::Type objectType = (Object::Type)stream.get8();

	// get unknown value
	uint16_t skippedShort = stream.get16();

	// grab location, size
	Vector3d position, size;
	position.x		= stream.get16();
	position.y		= stream.get16();
	position.z		= stream.get16();
	size.x			= stream.get16();
	size.y			= stream.get16();
	size.z			= stream.get16();

	// object ID
	uint16_t objectID = stream.get16();

	// size of object on disk; we've accounted for 20 bytes
	// already so we can subtract that to get the remaining
	// length beyond here
	uint32_t byteSizeOfObject = (uint32_t)(stream.get16() << 1) - 20;

	std::cout << "Object " << objectID << "; type " << (int)objectType << std::endl;

	switch(objectType)
	{
		default:
		{
			// read the appropriate number of colours
			int numberOfColours = GeometricObject::numberOfColoursForObjectOfType(objectType);
			std::vector<uint8_t> *colours = new std::vector<uint8_t>;
			for(uint8_t colour = 0; colour < numberOfColours; colour++)
			{
				colours->push_back(stream.get8());
				byteSizeOfObject--;
			}

			// read extra vertices if required...
			int numberOfOrdinates = GeometricObject::numberOfOrdinatesForType(objectType);
			std::vector<uint16_t> *ordinates = nullptr;

			if(numberOfOrdinates)
			{
				ordinates = new std::vector<uint16_t>;

				for(int ordinate = 0; ordinate < numberOfOrdinates; ordinate++)
				{
					ordinates->push_back(stream.get16());
					byteSizeOfObject -= 2;
				}
			}

			// grab the object condition, if there is one
			FCLInstructionVector instructions;
			if(byteSizeOfObject)
			{
				shared_ptr<vector<uint8_t>> conditionData = stream.nextBytes(byteSizeOfObject);

				shared_ptr<string> conditionSource = detokenise16bitCondition(*conditionData);
				instructions = getInstructions(conditionSource.get());
			}
			byteSizeOfObject = 0;

			// create an object
			return
				new GeometricObject(
					objectType,
					objectID,
					position,
					size,
					colours,
					ordinates,
					instructions);
		}
		break;

		case Object::Entrance:
		case Object::Sensor:
		case Object::Group:
		break;
	}

	// skip whatever we didn't understand
	stream.skipBytes(byteSizeOfObject);

	return nullptr;
}

static shared_ptr<Area> loadArea(StreamLoader &stream)
{
	// the lowest bit of this value seems to indicate
	// horizon on or off; this is as much as I currently know
	uint16_t skippedValue		= stream.get16();
	uint16_t numberOfObjects	= stream.get16();
	uint16_t areaNumber			= stream.get16();

	cout << "Area " << areaNumber << endl;
	cout << "Skipped value " << skippedValue << endl;
	cout << "Objects: " << numberOfObjects << endl;

	// I've yet to decipher this fully
	uint16_t horizonColour	= stream.get16();
	cout << "Horizon colour " << hex << (int)horizonColour << dec << endl;

	// this is just a complete guess
	for(int paletteEntry = 0; paletteEntry < 22; paletteEntry++)
	{
		uint8_t paletteColour		= stream.get8();
		cout << "Palette colour (?) " << hex << (int)paletteColour << dec << endl;
	}

	// we'll need to collate all objects and entrances; it's likely a
	// plain C array would do but maps are safer and the total application
	// cost is going to be negligible regardless
	ObjectMap *objectsByID = new ObjectMap;
	ObjectMap *entrancesByID = new ObjectMap;

	// get the objects or whatever; entrances use a unique numbering
	// system and have the high bit of their IDs set in the original file
	for(uint16_t object = 0; object < numberOfObjects; object++)
	{
		Object *newObject = loadObject(stream);

		if(newObject)
		{
			if(newObject->getType() == Object::Entrance)
			{
				(*entrancesByID)[newObject->getObjectID() & 0x7fff] = newObject;
			}
			else
			{
				(*objectsByID)[newObject->getObjectID()] = newObject;
			}
		}
	}

	return shared_ptr<Area>(new Area(areaNumber, objectsByID, entrancesByID));
}

Game *load16bitBinary(vector <uint8_t> &binary)
{
	StreamLoader streamLoader(binary);

	vector<uint8_t>::size_type baseOffset = 0;

	// check whether this looks like an Amiga game; if so it'll start with AM
	// XOR'd with the repeating byte pattern 0x71, 0xc1 or with the pattern
	// 0x88 0x2c if it's on the ST (though the signature will still be AM)
	uint16_t platformID = streamLoader.get16();

	if(
		(platformID != 0x4120)
//		(platformID == 12428) || (platformID == 51553)
	)
	{
		// TODO: record original platform type, so we can decode the palette
		// and possibly the border properly

		streamLoader.setReadMask((platformID >> 8) ^ 'A', (platformID & 0xff) ^ 'M');
	}
	else
	{
		// find DOS end of file and consume it
		while(!streamLoader.eof() && streamLoader.get8() != 0x1a);
		streamLoader.get8();

		// advance to the next two-byte boundary if necessary
		streamLoader.alignPointer();

		// skip bytes with meaning unknown
		streamLoader.get16();

		// this brings us to the beginning of the embedded
		// .KIT file, so we'll grab the base offset for
		// finding areas later
		baseOffset = streamLoader.getFileOffset();

		// check that the next two bytes are "PC", then
		// skip the number that comes after
		if(streamLoader.get8() != 'C' || streamLoader.get8() != 'P') return nullptr;
	}

	// skip an unknown meaning
	streamLoader.get16();

	// start grabbing some of the basics...

	uint16_t numberOfAreas = streamLoader.get16();
	streamLoader.get16();							// meaning unknown

	cout << numberOfAreas << " Areas" << endl;

	uint16_t windowCentreX	= streamLoader.get16();
	uint16_t windowCentreY	= streamLoader.get16();
	uint16_t windowWidth	= streamLoader.get16();
	uint16_t windowHeight	= streamLoader.get16();

	cout << "Window centre: ("	<< windowCentreX	<< ", " << windowCentreY	<< ")" << endl;
	cout << "Window size: ("	<< windowWidth		<< ", " << windowHeight		<< ")" << endl;

	uint16_t scaleX	= streamLoader.get16();
	uint16_t scaleY	= streamLoader.get16();
	uint16_t scaleZ	= streamLoader.get16();

	cout << "Scale: " << scaleX << ", " << scaleY << ", " << scaleZ << endl;

	uint16_t timerReload	= streamLoader.get16();

	cout << "Timer: every " << timerReload << " 50Hz frames";

	uint16_t maximumActivationDistance	= streamLoader.get16();
	uint16_t maximumFallDistance		= streamLoader.get16();
	uint16_t maximumClimbDistance		= streamLoader.get16();

	cout << "Maximum activation distance: "		<< maximumActivationDistance << endl;
	cout << "Maximum fall distance: "			<< maximumFallDistance << endl;
	cout << "Maximum climb distance: "			<< maximumClimbDistance << endl;

	uint16_t startArea					= streamLoader.get16();
	uint16_t startEntrance				= streamLoader.get16();

	cout << "Start at entrance " << startEntrance << " in area " << startArea << endl;

	uint16_t playerHeight				= streamLoader.get16();
	uint16_t playerStep					= streamLoader.get16();
	uint16_t playerAngle				= streamLoader.get16();

	cout << "Height " << playerHeight << ", stap " << playerStep << ", angle " << playerAngle << endl;

	uint16_t startVehicle				= streamLoader.get16();
	uint16_t executeGlobalCondition		= streamLoader.get16();

	cout << "Start vehicle " << startVehicle << ", execute global condition " << executeGlobalCondition << endl;

	// I haven't figured out what the next 106
	// bytes mean, so we'll skip them — global objects
	// maybe? Likely not 106 bytes in every file.
	//
	// ADDED: having rediscovered my source for the 8bit
	// file format, could this be shading information by
	// analogy with that?
	streamLoader.skipBytes(106);

	// at this point I should properly load the border/key/mouse
	// bindings, but I'm not worried about it for now.
	//
	// Format is:
	//		(left x, top y, right x, bottom y) - all 16 bit
	//		keyboard key as an ASCII character (or zero for none)
	//		mouse button masl; 00 = both, 01 = left, 02 = right
	//
	// So, 10 bytes per binding. Bindings are listed in the order:
	//
	//	move forwards, move backwards, move right, move left, rise,
	//	fall, turn left, turn right, look up, look down, tilt left,
	//	tilt right, face forward, u-turn, change vehicle type,
	//	select this vehicle, quit game, fire, activate object,
	//	centre cursor on/off, save game position, load game position
	//
	// So 35 total. Which means this area takes up 350 bytes.
	streamLoader.skipBytes(350);

	// there are then file pointers for every area — these are
	// the number of shorts from the 'PC' tag, so multiply by
	// two for bytes. Each is four bytes
	uint32_t *fileOffsetForArea = new uint32_t[numberOfAreas];
	for(uint16_t area = 0; area < numberOfAreas; area++)
		fileOffsetForArea[area] = (uint32_t)streamLoader.get32() << 1;

	// now come the global conditions
	uint16_t numberOfGlobalConditions = streamLoader.get16();
	for(uint16_t globalCondition = 0; globalCondition < numberOfGlobalConditions; globalCondition++)
	{
		// 12 bytes for the name of the condition;
		// we don't care
		streamLoader.skipBytes(12);

		// get the length and the data itself, converting from
		// shorts to bytes
		uint32_t lengthOfCondition = (uint32_t)streamLoader.get16() << 1;

		// get the condition
		shared_ptr<vector<uint8_t>> conditionData = streamLoader.nextBytes(lengthOfCondition);

		cout << "Global condition " << globalCondition+1 << endl;
		cout << *detokenise16bitCondition(*conditionData) << endl;
	}

	// grab the areas
	AreaMap *areaMap = new AreaMap;
	for(uint16_t area = 0; area < numberOfAreas; area++)
	{
//		cout << "Area " << area+1 << endl;

		streamLoader.setFileOffset(fileOffsetForArea[area] + baseOffset);
		shared_ptr<Area> newArea = loadArea(streamLoader);

		if(newArea.get())
		{
			(*areaMap)[newArea->getAreaID()] = newArea;
		}

		cout << endl;
	}

	delete[] fileOffsetForArea;
	return new Game(areaMap);
}
<|endoftext|>


<commit_before>#include "singletons.h"
#include "config.h"
#include "logging.h"
#include <exception>
#include "files.h"
#include "sourcefile.h"

MainConfig::MainConfig() {
  find_or_create_config_files();
  boost::property_tree::json_parser::read_json(Singleton::config_dir() + "config.json", cfg);
  Singleton::Config::window()->keybindings = cfg.get_child("keybindings");
  GenerateSource();
  GenerateDirectoryFilter();

  Singleton::Config::window()->theme_name=cfg.get<std::string>("gtk_theme.name");
  Singleton::Config::window()->theme_variant=cfg.get<std::string>("gtk_theme.variant");

  Singleton::Config::terminal()->make_command=cfg.get<std::string>("project.make_command");
  Singleton::Config::terminal()->cmake_command=cfg.get<std::string>("project.cmake_command");
}

void MainConfig::find_or_create_config_files() {
  std::vector<std::string> files = {"config.json", "menu.xml", "plugins.py"};
  boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir()));
  for (auto &file : files) {
    auto path = boost::filesystem::path(Singleton::config_dir() + file);
    if (!boost::filesystem::is_regular_file(path)) {
      if (file == "config.json") juci::filesystem::write(path, configjson);
      if (file == "plugins.py") juci::filesystem::write(path, pluginspy);
      if (file == "menu.xml") juci::filesystem::write(path, menuxml);
    }
  }

  boost::filesystem::create_directories(boost::filesystem::path(Singleton::style_dir()));
  boost::filesystem::path juci_style_path=Singleton::style_dir();
  juci_style_path+="juci-light.xml";
  if(!boost::filesystem::exists(juci_style_path))
    juci::filesystem::write(juci_style_path, juci_light_style);
  juci_style_path=Singleton::style_dir();
  juci_style_path+="juci-dark.xml";
  if(!boost::filesystem::exists(juci_style_path))
    juci::filesystem::write(juci_style_path, juci_dark_style);
}

void MainConfig::GenerateSource() {
  auto source_cfg = Singleton::Config::source();
  auto source_json = cfg.get_child("source");

  source_cfg->spellcheck_language = source_json.get<std::string>("spellcheck_language");

  source_cfg->default_tab_char = source_json.get<char>("default_tab_char");
  source_cfg->default_tab_size = source_json.get<unsigned>("default_tab_size");
  source_cfg->auto_tab_char_and_size = source_json.get<bool>("auto_tab_char_and_size");

  source_cfg->wrap_lines = source_json.get_value<bool>("wrap_lines");

  source_cfg->highlight_current_line = source_json.get_value<bool>("highlight_current_line");
  source_cfg->show_line_numbers = source_json.get_value<bool>("show_line_numbers");

  for (auto &i : source_json.get_child("clang_types"))
    source_cfg->clang_types[i.first] = i.second.get_value<std::string>();

  Singleton::Config::source()->style=source_json.get<std::string>("style");
  source_cfg->font=source_json.get<std::string>("font");
}

void MainConfig::GenerateDirectoryFilter() {
  auto dir_cfg=Singleton::Config::directories();
  DEBUG("Fetching directory filter");
  boost::property_tree::ptree dir_json = cfg.get_child("directoryfilter");
  boost::property_tree::ptree ignore_json = dir_json.get_child("ignore");
  boost::property_tree::ptree except_json = dir_json.get_child("exceptions");
  for ( auto &i : except_json )
    dir_cfg->exceptions.emplace_back(i.second.get_value<std::string>());
  for ( auto &i : ignore_json )
    dir_cfg->ignored.emplace_back(i.second.get_value<std::string>());
  DEBUG("Directory filter fetched");
}
<commit_msg>Fixed bug when reading config.json.<commit_after>#include "singletons.h"
#include "config.h"
#include "logging.h"
#include <exception>
#include "files.h"
#include "sourcefile.h"

MainConfig::MainConfig() {
  find_or_create_config_files();
  boost::property_tree::json_parser::read_json(Singleton::config_dir() + "config.json", cfg);
  Singleton::Config::window()->keybindings = cfg.get_child("keybindings");
  GenerateSource();
  GenerateDirectoryFilter();

  Singleton::Config::window()->theme_name=cfg.get<std::string>("gtk_theme.name");
  Singleton::Config::window()->theme_variant=cfg.get<std::string>("gtk_theme.variant");

  Singleton::Config::terminal()->make_command=cfg.get<std::string>("project.make_command");
  Singleton::Config::terminal()->cmake_command=cfg.get<std::string>("project.cmake_command");
}

void MainConfig::find_or_create_config_files() {
  std::vector<std::string> files = {"config.json", "menu.xml", "plugins.py"};
  boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir()));
  for (auto &file : files) {
    auto path = boost::filesystem::path(Singleton::config_dir() + file);
    if (!boost::filesystem::is_regular_file(path)) {
      if (file == "config.json") juci::filesystem::write(path, configjson);
      if (file == "plugins.py") juci::filesystem::write(path, pluginspy);
      if (file == "menu.xml") juci::filesystem::write(path, menuxml);
    }
  }

  boost::filesystem::create_directories(boost::filesystem::path(Singleton::style_dir()));
  boost::filesystem::path juci_style_path=Singleton::style_dir();
  juci_style_path+="juci-light.xml";
  if(!boost::filesystem::exists(juci_style_path))
    juci::filesystem::write(juci_style_path, juci_light_style);
  juci_style_path=Singleton::style_dir();
  juci_style_path+="juci-dark.xml";
  if(!boost::filesystem::exists(juci_style_path))
    juci::filesystem::write(juci_style_path, juci_dark_style);
}

void MainConfig::GenerateSource() {
  auto source_cfg = Singleton::Config::source();
  auto source_json = cfg.get_child("source");

  source_cfg->spellcheck_language = source_json.get<std::string>("spellcheck_language");

  source_cfg->default_tab_char = source_json.get<char>("default_tab_char");
  source_cfg->default_tab_size = source_json.get<unsigned>("default_tab_size");
  source_cfg->auto_tab_char_and_size = source_json.get<bool>("auto_tab_char_and_size");

  source_cfg->wrap_lines = source_json.get<bool>("wrap_lines");

  source_cfg->highlight_current_line = source_json.get<bool>("highlight_current_line");
  source_cfg->show_line_numbers = source_json.get<bool>("show_line_numbers");

  for (auto &i : source_json.get_child("clang_types"))
    source_cfg->clang_types[i.first] = i.second.get_value<std::string>();

  Singleton::Config::source()->style=source_json.get<std::string>("style");
  source_cfg->font=source_json.get<std::string>("font");
}

void MainConfig::GenerateDirectoryFilter() {
  auto dir_cfg=Singleton::Config::directories();
  DEBUG("Fetching directory filter");
  boost::property_tree::ptree dir_json = cfg.get_child("directoryfilter");
  boost::property_tree::ptree ignore_json = dir_json.get_child("ignore");
  boost::property_tree::ptree except_json = dir_json.get_child("exceptions");
  for ( auto &i : except_json )
    dir_cfg->exceptions.emplace_back(i.second.get_value<std::string>());
  for ( auto &i : ignore_json )
    dir_cfg->ignored.emplace_back(i.second.get_value<std::string>());
  DEBUG("Directory filter fetched");
}
<|endoftext|>


<commit_before><commit_msg>FEM: [skip ci] support Line and Plane objects in Constraint::getDirection()<commit_after><|endoftext|>


<commit_before>/*********************************************************************
** Author: Zach Colbert
** Date: 1 November 2017
** Description:
*********************************************************************/

// Pre-processing includes pre-requisite libraries for the functions below
#include <string>

// Make sure to include the header file where we declare the player and team classes!
#include "Player.hpp"
#include "Team.hpp"

/*********************************************************************
** Description: The default constructor for the Player class takes no arguments, and sets the player's name and stats to default values.

Default name: ""
Default stats: -1
*********************************************************************/

Player::Player()
{
    // Set player name to empty string
    setName("");

    // Set player stats to -1
    setPoints(-1);
    setRebounds(-1);
    setAssists(-1);
}

// This class doesn't get a default constructor, because there's no "I" in "Team"
//  REPLACE THIS COMMEMTN!!!!!!!
 Team::Team(Player::Player point_Guard, Player::Player shooting_Guard, Player::Player small_Forward, Player::Player power_Forward, Player::Player center_In)
 {
    // Set each of the positions using mutator functions
    setPointGuard(point_Guard);
    setShootingGuard(shooting_Guard);
    setSmallForward(small_Forward);
    setPowerForward(power_Forward);
    setCenter(center_In);
 }

// Mutator for pointGuard
void setPointGuard(Player::Player p)
{
    pointGuard = p;
}

// Accessor for pointGuard
Player::Player getPointGuard()
{
    return pointGuard;
}

// Mutator for shootingGuard
void setShootingGuard(Player::Player p)
{
    shootingGuard = p;
}

// Accessor for shootingGuard
Player::Player getShootingGuard()
{
    return shootingGuard;
}

// Mutator for smallForward
void setSmallForward(Player::Player p)
{
    smallForward = p;
}

// Accessor for smallForward
Player::Player getSmallForward()
{
    return smallForward;
}

// Mutator for powerForward
void setPowerForward(Player::Player p)
{
    powerForward = p;
}

// Accessor for powerForward
Player::Player getPowerForward()
{
    return powerForward;
}

// Mutator for center
void setCenter(Player::Player p)
{
    center = p;
}

// Accessor for center
Player::Player getCenter()
{
    return center;
}

// totalPoints gets the points attribute from each of the member variables, and returns the total
// REPLACE THIS COMMENT!!!!!!!!
int totalPoints()
{
    return pointGuard.getPoints() + shootingGuard.getPoints() + smallForward.getPoints() + powerForward.getPoints() + center.getPoints();
}<commit_msg>Comments finished<commit_after>/*********************************************************************
** Author: Zach Colbert
** Date: 1 November 2017
** Description:
*********************************************************************/

// Pre-processing includes pre-requisite libraries for the functions below
#include <string>

// Make sure to include the header file where we declare the player and team classes!
#include "Player.hpp"
#include "Team.hpp"

/*********************************************************************
** Description: The constructor for the Team class takes five objects of the Player type as arguments, and sets them as positions on the team. Those positions are, in this order:

** Point Guard
** Shooting Guard
** Small Forward
** Power Forward
** Center

This class does not have a default constructor because there is no "I" in "Team."

** Example: Team::Team myTeam(pointGuard, shootingGuard, smallForward, powerForward, center);
*********************************************************************/
 Team::Team(Player::Player point_Guard, Player::Player shooting_Guard, Player::Player small_Forward, Player::Player power_Forward, Player::Player center_In)
 {
    // Set each of the positions using mutator functions
    setPointGuard(point_Guard);
    setShootingGuard(shooting_Guard);
    setSmallForward(small_Forward);
    setPowerForward(power_Forward);
    setCenter(center_In);
 }

// Mutator for pointGuard
void setPointGuard(Player::Player p)
{
    pointGuard = p;
}

// Accessor for pointGuard
Player::Player getPointGuard()
{
    return pointGuard;
}

// Mutator for shootingGuard
void setShootingGuard(Player::Player p)
{
    shootingGuard = p;
}

// Accessor for shootingGuard
Player::Player getShootingGuard()
{
    return shootingGuard;
}

// Mutator for smallForward
void setSmallForward(Player::Player p)
{
    smallForward = p;
}

// Accessor for smallForward
Player::Player getSmallForward()
{
    return smallForward;
}

// Mutator for powerForward
void setPowerForward(Player::Player p)
{
    powerForward = p;
}

// Accessor for powerForward
Player::Player getPowerForward()
{
    return powerForward;
}

// Mutator for center
void setCenter(Player::Player p)
{
    center = p;
}

// Accessor for center
Player::Player getCenter()
{
    return center;
}

/*********************************************************************
** Description: The totalPoints function of the Team class gets the points attribute from each Player object in the team, sums them, and returns the total value of points of all players on the team.

** Example: myTeam.totalPoints();
** Example Output: 12;
*********************************************************************/
int totalPoints()
{
    return pointGuard.getPoints() + shootingGuard.getPoints() + smallForward.getPoints() + powerForward.getPoints() + center.getPoints();
}<|endoftext|>


<commit_before>#include "MicroBit.h"

char MICROBIT_BLE_DEVICE_NAME[] = "BBC MicroBit [xxxxx]";

#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED) && CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
const char MICROBIT_BLE_MANUFACTURER[] = "The Cast of W1A";
const char MICROBIT_BLE_MODEL[] = "Microbit SB2";
const char MICROBIT_BLE_SERIAL[] = "SN1";
const char MICROBIT_BLE_HARDWARE_VERSION[] = "0.2";
const char MICROBIT_BLE_FIRMWARE_VERSION[] = "1.1";
const char MICROBIT_BLE_SOFTWARE_VERSION[] = "1.0";
#endif

/**
  * custom function for panic for malloc & new due to scoping issue.
  */
void panic(int statusCode)
{
    uBit.panic(statusCode);
}

/**
  * Callback when a BLE GATT disconnect occurs.
  */
void bleDisconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    uBit.ble->startAdvertising();
}

/**
  * Constructor.
  * Create a representation of a MicroBit device as a global singleton.
  * @param messageBus callback function to receive MicroBitMessageBus events.
  *
  * Exposed objects:
  * @code
  * uBit.systemTicker; //the Ticker callback that performs routines like updating the display.
  * uBit.MessageBus; //The message bus where events are fired.
  * uBit.display; //The display object for the LED matrix.
  * uBit.buttonA; //The buttonA object for button a.
  * uBit.buttonB; //The buttonB object for button b.
  * uBit.buttonAB; //The buttonAB object for button a+b multi press.
  * uBit.resetButton; //The resetButton used for soft resets.
  * uBit.accelerometer; //The object that represents the inbuilt accelerometer
  * uBit.compass; //The object that represents the inbuilt compass(magnetometer)
  * uBit.io.P*; //Where P* is P0 to P16, P19 & P20 on the edge connector
  * @endcode
  */
MicroBit::MicroBit() :
    flags(0x00),
    i2c(MICROBIT_PIN_SDA, MICROBIT_PIN_SCL),
#if CONFIG_DISABLED(MICROBIT_DBG)
    serial(USBTX, USBRX),
#endif
    MessageBus(),
    display(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_WIDTH, MICROBIT_DISPLAY_HEIGHT),
    buttonA(MICROBIT_ID_BUTTON_A,MICROBIT_PIN_BUTTON_A),
    buttonB(MICROBIT_ID_BUTTON_B,MICROBIT_PIN_BUTTON_B),
    buttonAB(MICROBIT_ID_BUTTON_AB,MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B),
    accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR),
    compass(MICROBIT_ID_COMPASS, MAG3110_DEFAULT_ADDR),
    thermometer(MICROBIT_ID_THERMOMETER),
    io(MICROBIT_ID_IO_P0,MICROBIT_ID_IO_P1,MICROBIT_ID_IO_P2,
       MICROBIT_ID_IO_P3,MICROBIT_ID_IO_P4,MICROBIT_ID_IO_P5,
       MICROBIT_ID_IO_P6,MICROBIT_ID_IO_P7,MICROBIT_ID_IO_P8,
       MICROBIT_ID_IO_P9,MICROBIT_ID_IO_P10,MICROBIT_ID_IO_P11,
       MICROBIT_ID_IO_P12,MICROBIT_ID_IO_P13,MICROBIT_ID_IO_P14,
       MICROBIT_ID_IO_P15,MICROBIT_ID_IO_P16,MICROBIT_ID_IO_P19,
       MICROBIT_ID_IO_P20)
{
}

/**
  * Post constructor initialisation method.
  * After *MUCH* pain, it's noted that the BLE stack can't be brought up in a
  * static context, so we bring it up here rather than in the constructor.
  * n.b. This method *must* be called in main() or later, not before.
  *
  * Example:
  * @code
  * uBit.init();
  * @endcode
  */
void MicroBit::init()
{
    //add the display to the systemComponent array
    addSystemComponent(&uBit.display);

    //add the compass and accelerometer to the idle array
    addIdleComponent(&uBit.accelerometer);
    addIdleComponent(&uBit.compass);
    addIdleComponent(&uBit.MessageBus);

    // Seed our random number generator
    seedRandom();

#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
    // Start the BLE stack.

    ble = new BLEDevice();
    ble->init();
    ble->onDisconnection(bleDisconnectionCallback);

    // Bring up any configured auxiliary services.

#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
    ble_firmware_update_service = new MicroBitDFUService(*ble);

    // Compute our auto-generated MicroBit device name.
    ble_firmware_update_service->getName(MICROBIT_BLE_DEVICE_NAME+14);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
    DeviceInformationService ble_device_information_service (*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, MICROBIT_BLE_SERIAL, MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE)
    ble_event_service = new MicroBitEventService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_LED_SERVICE)
    ble_led_service = new MicroBitLEDService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
    ble_accelerometer_service = new MicroBitAccelerometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_MAGNETOMETER_SERVICE)
    ble_magnetometer_service = new MicroBitMagnetometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_BUTTON_SERVICE)
    ble_button_service = new MicroBitButtonService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_IO_PIN_SERVICE)
    ble_io_pin_service = new MicroBitIOPinService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_TEMPERATURE_SERVICE)
    ble_temperature_service = new MicroBitTemperatureService(*ble);
#endif

    // Setup advertising.
    ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)MICROBIT_BLE_DEVICE_NAME, sizeof(MICROBIT_BLE_DEVICE_NAME));
    ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble->setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));
    ble->startAdvertising();
#endif

    // Start refreshing the Matrix Display
    systemTicker.attach(this, &MicroBit::systemTick, MICROBIT_DISPLAY_REFRESH_PERIOD);
}

/**
  * Will reset the micro:bit when called.
  *
  * Example:
  * @code
  * uBit.reset();
  * @endcode
  */
void MicroBit::reset()
{
  reset();
}

/**
  * Delay for the given amount of time.
  * If the scheduler is running, this will deschedule the current fiber and perform
  * a power efficent, concurrent sleep operation.
  * If the scheduler is disabled or we're running in an interrupt context, this
  * will revert to a busy wait.
  *
  * @note Values of 6 and below tend to lose resolution - do you really need to sleep for this short amount of time?
  *
  * @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
  *
  * Example:
  * @code
  * uBit.sleep(20); //sleep for 20ms
  * @endcode
  */
void MicroBit::sleep(int milliseconds)
{
    //sanity check, we can't time travel... (yet?)
    if(milliseconds < 0)
        return;

    if (flags & MICROBIT_FLAG_SCHEDULER_RUNNING)
        fiber_sleep(milliseconds);
    else
        wait_ms(milliseconds);
}

/**
  * Generate a random number in the given range.
  * We use a simple Galois LFSR random number generator here,
  * as a Galois LFSR is sufficient for our applications, and much more lightweight
  * than the hardware random number generator built int the processor, which takes
  * a long time and uses a lot of energy.
  *
  * KIDS: You shouldn't use this is the real world to generte cryptographic keys though...
  * have a think why not. :-)
  *
  * @param max the upper range to generate a number for. This number cannot be negative
  * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE (defined in ErrorNo.h) if max is <= 0.
  *
  * Example:
  * @code
  * uBit.random(200); //a number between 0 and 199
  * @endcode
  */
int MicroBit::random(int max)
{
    //return MICROBIT_INVALID_VALUE if max is <= 0...
    if(max <= 0)
        return MICROBIT_INVALID_VALUE;

    // Cycle the LFSR (Linear Feedback Shift Register).
    // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneider here (a true legend in the field!),
    // For those interested, it's documented in his paper:
    // "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent generator for 32-bit Microprocessors"

    randomValue = ((((randomValue >> 31) ^ (randomValue >> 6) ^ (randomValue >> 4) ^ (randomValue >> 2) ^ (randomValue >> 1) ^ randomValue) & 0x0000001) << 31 ) | (randomValue >> 1);
    return randomValue % max;
}

/**
  * Seed our a random number generator (RNG).
  * We use the NRF51822 in built cryptographic random number generator to seed a Galois LFSR.
  * We do this as the hardware RNG is relatively high power, and use the the BLE stack internally,
  * with a less than optimal application interface. A Galois LFSR is sufficient for our
  * applications, and much more lightweight.
  */
void MicroBit::seedRandom()
{
    randomValue = 0;

    // Start the Random number generator. No need to leave it running... I hope. :-)
    NRF_RNG->TASKS_START = 1;

    for(int i = 0; i < 4 ;i++)
    {
        // Clear the VALRDY EVENT
        NRF_RNG->EVENTS_VALRDY = 0;

        // Wait for a number ot be generated.
        while ( NRF_RNG->EVENTS_VALRDY == 0);

        randomValue = (randomValue << 8) | ((int) NRF_RNG->VALUE);
    }

    // Disable the generator to save power.
    NRF_RNG->TASKS_STOP = 1;
}

/**
  * Periodic callback. Used by MicroBitDisplay, FiberScheduler and buttons.
  */
void MicroBit::systemTick()
{
    // Scheduler callback. We do this here just as a single timer is more efficient. :-)
    if (uBit.flags & MICROBIT_FLAG_SCHEDULER_RUNNING)
        scheduler_tick();

    //work out if any idle components need processing, if so prioritise the idle thread
    for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
        if(idleThreadComponents[i] != NULL && idleThreadComponents[i]->isIdleCallbackNeeded())
        {
            fiber_flags |= MICROBIT_FLAG_DATA_READY;
            break;
        }

    //update any components in the systemComponents array
    for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++)
        if(systemTickComponents[i] != NULL)
            systemTickComponents[i]->systemTick();
}

/**
  * System tasks to be executed by the idle thread when the Micro:Bit isn't busy or when data needs to be read.
  */
void MicroBit::systemTasks()
{
    //call the idleTick member function indiscriminately
    for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
        if(idleThreadComponents[i] != NULL)
            idleThreadComponents[i]->idleTick();

    fiber_flags &= ~MICROBIT_FLAG_DATA_READY;
}

/**
  * add a component to the array of components which invocate the systemTick member function during a systemTick
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::addSystemComponent(MicroBitComponent *component)
{
    int i = 0;

    while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS)
        i++;

    if(i == MICROBIT_SYSTEM_COMPONENTS)
        return;

    systemTickComponents[i] = component;
}

/**
  * remove a component from the array of components
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::removeSystemComponent(MicroBitComponent *component)
{
    int i = 0;

    while(systemTickComponents[i] != component  && i < MICROBIT_SYSTEM_COMPONENTS)
        i++;

    if(i == MICROBIT_SYSTEM_COMPONENTS)
        return;

    systemTickComponents[i] = NULL;
}

/**
  * add a component to the array of components which invocate the systemTick member function during a systemTick
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::addIdleComponent(MicroBitComponent *component)
{
    int i = 0;

    while(idleThreadComponents[i] != NULL && i < MICROBIT_IDLE_COMPONENTS)
        i++;

    if(i == MICROBIT_IDLE_COMPONENTS)
        return;

    idleThreadComponents[i] = component;
}

/**
  * remove a component from the array of components
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::removeIdleComponent(MicroBitComponent *component)
{
    int i = 0;

    while(idleThreadComponents[i] != component  && i < MICROBIT_IDLE_COMPONENTS)
        i++;

    if(i == MICROBIT_IDLE_COMPONENTS)
        return;

    idleThreadComponents[i] = NULL;
}

/**
  * Determine the time since this MicroBit was last reset.
  *
  * @return The time since the last reset, in milliseconds. This will result in overflow after 1.6 months.
  * TODO: handle overflow case.
  */
unsigned long MicroBit::systemTime()
{
    return ticks;
}

/**
  * Triggers a microbit panic where an infinite loop will occur swapping between the panicFace and statusCode if provided.
  *
  * @param statusCode the status code of the associated error. Status codes must be in the range 0-255.
  */
void MicroBit::panic(int statusCode)
{
    //show error and enter infinite while
    uBit.display.error(statusCode);
}

<commit_msg>microbit: Updated Bluetooth device name from MicroBit to micro:bit to match brand guidelines<commit_after>#include "MicroBit.h"

char MICROBIT_BLE_DEVICE_NAME[] = "BBC micro:bit [xxxxx]";

#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED) && CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
const char MICROBIT_BLE_MANUFACTURER[] = "The Cast of W1A";
const char MICROBIT_BLE_MODEL[] = "micro:bit";
const char MICROBIT_BLE_SERIAL[] = "SN1";
const char MICROBIT_BLE_HARDWARE_VERSION[] = "0.2";
const char MICROBIT_BLE_FIRMWARE_VERSION[] = "1.1";
const char MICROBIT_BLE_SOFTWARE_VERSION[] = "1.0";
#endif

/**
  * custom function for panic for malloc & new due to scoping issue.
  */
void panic(int statusCode)
{
    uBit.panic(statusCode);
}

/**
  * Callback when a BLE GATT disconnect occurs.
  */
void bleDisconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    uBit.ble->startAdvertising();
}

/**
  * Constructor.
  * Create a representation of a MicroBit device as a global singleton.
  * @param messageBus callback function to receive MicroBitMessageBus events.
  *
  * Exposed objects:
  * @code
  * uBit.systemTicker; //the Ticker callback that performs routines like updating the display.
  * uBit.MessageBus; //The message bus where events are fired.
  * uBit.display; //The display object for the LED matrix.
  * uBit.buttonA; //The buttonA object for button a.
  * uBit.buttonB; //The buttonB object for button b.
  * uBit.buttonAB; //The buttonAB object for button a+b multi press.
  * uBit.resetButton; //The resetButton used for soft resets.
  * uBit.accelerometer; //The object that represents the inbuilt accelerometer
  * uBit.compass; //The object that represents the inbuilt compass(magnetometer)
  * uBit.io.P*; //Where P* is P0 to P16, P19 & P20 on the edge connector
  * @endcode
  */
MicroBit::MicroBit() :
    flags(0x00),
    i2c(MICROBIT_PIN_SDA, MICROBIT_PIN_SCL),
#if CONFIG_DISABLED(MICROBIT_DBG)
    serial(USBTX, USBRX),
#endif
    MessageBus(),
    display(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_WIDTH, MICROBIT_DISPLAY_HEIGHT),
    buttonA(MICROBIT_ID_BUTTON_A,MICROBIT_PIN_BUTTON_A),
    buttonB(MICROBIT_ID_BUTTON_B,MICROBIT_PIN_BUTTON_B),
    buttonAB(MICROBIT_ID_BUTTON_AB,MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B),
    accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR),
    compass(MICROBIT_ID_COMPASS, MAG3110_DEFAULT_ADDR),
    thermometer(MICROBIT_ID_THERMOMETER),
    io(MICROBIT_ID_IO_P0,MICROBIT_ID_IO_P1,MICROBIT_ID_IO_P2,
       MICROBIT_ID_IO_P3,MICROBIT_ID_IO_P4,MICROBIT_ID_IO_P5,
       MICROBIT_ID_IO_P6,MICROBIT_ID_IO_P7,MICROBIT_ID_IO_P8,
       MICROBIT_ID_IO_P9,MICROBIT_ID_IO_P10,MICROBIT_ID_IO_P11,
       MICROBIT_ID_IO_P12,MICROBIT_ID_IO_P13,MICROBIT_ID_IO_P14,
       MICROBIT_ID_IO_P15,MICROBIT_ID_IO_P16,MICROBIT_ID_IO_P19,
       MICROBIT_ID_IO_P20)
{
}

/**
  * Post constructor initialisation method.
  * After *MUCH* pain, it's noted that the BLE stack can't be brought up in a
  * static context, so we bring it up here rather than in the constructor.
  * n.b. This method *must* be called in main() or later, not before.
  *
  * Example:
  * @code
  * uBit.init();
  * @endcode
  */
void MicroBit::init()
{
    //add the display to the systemComponent array
    addSystemComponent(&uBit.display);

    //add the compass and accelerometer to the idle array
    addIdleComponent(&uBit.accelerometer);
    addIdleComponent(&uBit.compass);
    addIdleComponent(&uBit.MessageBus);

    // Seed our random number generator
    seedRandom();

#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
    // Start the BLE stack.

    ble = new BLEDevice();
    ble->init();
    ble->onDisconnection(bleDisconnectionCallback);

    // Bring up any configured auxiliary services.

#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
    ble_firmware_update_service = new MicroBitDFUService(*ble);

    // Compute our auto-generated MicroBit device name.
    ble_firmware_update_service->getName(MICROBIT_BLE_DEVICE_NAME+15);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
    DeviceInformationService ble_device_information_service (*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, MICROBIT_BLE_SERIAL, MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE)
    ble_event_service = new MicroBitEventService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_LED_SERVICE)
    ble_led_service = new MicroBitLEDService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
    ble_accelerometer_service = new MicroBitAccelerometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_MAGNETOMETER_SERVICE)
    ble_magnetometer_service = new MicroBitMagnetometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_BUTTON_SERVICE)
    ble_button_service = new MicroBitButtonService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_IO_PIN_SERVICE)
    ble_io_pin_service = new MicroBitIOPinService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_TEMPERATURE_SERVICE)
    ble_temperature_service = new MicroBitTemperatureService(*ble);
#endif

    // Setup advertising.
    ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)MICROBIT_BLE_DEVICE_NAME, sizeof(MICROBIT_BLE_DEVICE_NAME));
    ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble->setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));
    ble->startAdvertising();
#endif

    // Start refreshing the Matrix Display
    systemTicker.attach(this, &MicroBit::systemTick, MICROBIT_DISPLAY_REFRESH_PERIOD);
}

/**
  * Will reset the micro:bit when called.
  *
  * Example:
  * @code
  * uBit.reset();
  * @endcode
  */
void MicroBit::reset()
{
  reset();
}

/**
  * Delay for the given amount of time.
  * If the scheduler is running, this will deschedule the current fiber and perform
  * a power efficent, concurrent sleep operation.
  * If the scheduler is disabled or we're running in an interrupt context, this
  * will revert to a busy wait.
  *
  * @note Values of 6 and below tend to lose resolution - do you really need to sleep for this short amount of time?
  *
  * @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
  *
  * Example:
  * @code
  * uBit.sleep(20); //sleep for 20ms
  * @endcode
  */
void MicroBit::sleep(int milliseconds)
{
    //sanity check, we can't time travel... (yet?)
    if(milliseconds < 0)
        return;

    if (flags & MICROBIT_FLAG_SCHEDULER_RUNNING)
        fiber_sleep(milliseconds);
    else
        wait_ms(milliseconds);
}

/**
  * Generate a random number in the given range.
  * We use a simple Galois LFSR random number generator here,
  * as a Galois LFSR is sufficient for our applications, and much more lightweight
  * than the hardware random number generator built int the processor, which takes
  * a long time and uses a lot of energy.
  *
  * KIDS: You shouldn't use this is the real world to generte cryptographic keys though...
  * have a think why not. :-)
  *
  * @param max the upper range to generate a number for. This number cannot be negative
  * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE (defined in ErrorNo.h) if max is <= 0.
  *
  * Example:
  * @code
  * uBit.random(200); //a number between 0 and 199
  * @endcode
  */
int MicroBit::random(int max)
{
    //return MICROBIT_INVALID_VALUE if max is <= 0...
    if(max <= 0)
        return MICROBIT_INVALID_VALUE;

    // Cycle the LFSR (Linear Feedback Shift Register).
    // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneider here (a true legend in the field!),
    // For those interested, it's documented in his paper:
    // "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent generator for 32-bit Microprocessors"

    randomValue = ((((randomValue >> 31) ^ (randomValue >> 6) ^ (randomValue >> 4) ^ (randomValue >> 2) ^ (randomValue >> 1) ^ randomValue) & 0x0000001) << 31 ) | (randomValue >> 1);
    return randomValue % max;
}

/**
  * Seed our a random number generator (RNG).
  * We use the NRF51822 in built cryptographic random number generator to seed a Galois LFSR.
  * We do this as the hardware RNG is relatively high power, and use the the BLE stack internally,
  * with a less than optimal application interface. A Galois LFSR is sufficient for our
  * applications, and much more lightweight.
  */
void MicroBit::seedRandom()
{
    randomValue = 0;

    // Start the Random number generator. No need to leave it running... I hope. :-)
    NRF_RNG->TASKS_START = 1;

    for(int i = 0; i < 4 ;i++)
    {
        // Clear the VALRDY EVENT
        NRF_RNG->EVENTS_VALRDY = 0;

        // Wait for a number ot be generated.
        while ( NRF_RNG->EVENTS_VALRDY == 0);

        randomValue = (randomValue << 8) | ((int) NRF_RNG->VALUE);
    }

    // Disable the generator to save power.
    NRF_RNG->TASKS_STOP = 1;
}

/**
  * Periodic callback. Used by MicroBitDisplay, FiberScheduler and buttons.
  */
void MicroBit::systemTick()
{
    // Scheduler callback. We do this here just as a single timer is more efficient. :-)
    if (uBit.flags & MICROBIT_FLAG_SCHEDULER_RUNNING)
        scheduler_tick();

    //work out if any idle components need processing, if so prioritise the idle thread
    for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
        if(idleThreadComponents[i] != NULL && idleThreadComponents[i]->isIdleCallbackNeeded())
        {
            fiber_flags |= MICROBIT_FLAG_DATA_READY;
            break;
        }

    //update any components in the systemComponents array
    for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++)
        if(systemTickComponents[i] != NULL)
            systemTickComponents[i]->systemTick();
}

/**
  * System tasks to be executed by the idle thread when the Micro:Bit isn't busy or when data needs to be read.
  */
void MicroBit::systemTasks()
{
    //call the idleTick member function indiscriminately
    for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
        if(idleThreadComponents[i] != NULL)
            idleThreadComponents[i]->idleTick();

    fiber_flags &= ~MICROBIT_FLAG_DATA_READY;
}

/**
  * add a component to the array of components which invocate the systemTick member function during a systemTick
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::addSystemComponent(MicroBitComponent *component)
{
    int i = 0;

    while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS)
        i++;

    if(i == MICROBIT_SYSTEM_COMPONENTS)
        return;

    systemTickComponents[i] = component;
}

/**
  * remove a component from the array of components
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::removeSystemComponent(MicroBitComponent *component)
{
    int i = 0;

    while(systemTickComponents[i] != component  && i < MICROBIT_SYSTEM_COMPONENTS)
        i++;

    if(i == MICROBIT_SYSTEM_COMPONENTS)
        return;

    systemTickComponents[i] = NULL;
}

/**
  * add a component to the array of components which invocate the systemTick member function during a systemTick
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::addIdleComponent(MicroBitComponent *component)
{
    int i = 0;

    while(idleThreadComponents[i] != NULL && i < MICROBIT_IDLE_COMPONENTS)
        i++;

    if(i == MICROBIT_IDLE_COMPONENTS)
        return;

    idleThreadComponents[i] = component;
}

/**
  * remove a component from the array of components
  * @note this will be converted into a dynamic list of components
  */
void MicroBit::removeIdleComponent(MicroBitComponent *component)
{
    int i = 0;

    while(idleThreadComponents[i] != component  && i < MICROBIT_IDLE_COMPONENTS)
        i++;

    if(i == MICROBIT_IDLE_COMPONENTS)
        return;

    idleThreadComponents[i] = NULL;
}

/**
  * Determine the time since this MicroBit was last reset.
  *
  * @return The time since the last reset, in milliseconds. This will result in overflow after 1.6 months.
  * TODO: handle overflow case.
  */
unsigned long MicroBit::systemTime()
{
    return ticks;
}

/**
  * Triggers a microbit panic where an infinite loop will occur swapping between the panicFace and statusCode if provided.
  *
  * @param statusCode the status code of the associated error. Status codes must be in the range 0-255.
  */
void MicroBit::panic(int statusCode)
{
    //show error and enter infinite while
    uBit.display.error(statusCode);
}

<|endoftext|>