<commit_before>#include "netstream.h"

namespace openalpp {

NetStream::NetStream(ost::UDPSocket *socket,ost::TCPStream *controlsocket)
  : Stream() {
  if(controlsocket)
    ; // read stuff from it
  else
    ; // set defaults
  /*  updater_=new NetUpdater(socket_,controlsocket_,
			  buffername_,buffer2_->GetName(),
			  format_,frequency_,packetsize_);*/
}

NetStream::NetStream(ost::UDPSocket *socket,SampleFormat format,
		     unsigned int frequency,unsigned int packetsize)
  : Stream() {
  ALenum alformat=0;
  switch(format) {
    case(Mono8):
      alformat=AL_FORMAT_MONO8;
      break;
    case(Mono16):
      alformat=AL_FORMAT_MONO16;
      break;
    case(Stereo8):
      alformat=AL_FORMAT_STEREO8;
      break;
    case(Stereo16):
      alformat=AL_FORMAT_STEREO16;
      break;
  }
  updater_=new NetUpdater(socket,NULL,buffername_,buffer2_->GetName(),
			  alformat,frequency,packetsize);
}

NetStream::NetStream(const NetStream &stream) : Stream((const Stream &)stream){
}

NetStream::~NetStream() {
}

NetStream &NetStream::operator=(const NetStream &stream) {
  return *this;
}

}

<commit_msg>Minor additions<commit_after>#include "netstream.h"

namespace openalpp {

NetStream::NetStream(ost::UDPSocket *socket,ost::TCPStream *controlsocket)
  : Stream() {
  // TODO: Implement this
  if(controlsocket)
    ; // read stuff from it
  else
    ; // set defaults
  /*  updater_=new NetUpdater(socket_,controlsocket_,
			  buffername_,buffer2_->GetName(),
			  format_,frequency_,packetsize_);*/
}

NetStream::NetStream(ost::UDPSocket *socket,SampleFormat format,
		     unsigned int frequency,unsigned int packetsize)
  : Stream() {
  ALenum alformat=0;
  switch(format) {
    case(Mono8):
      alformat=AL_FORMAT_MONO8;
      break;
    case(Mono16):
      alformat=AL_FORMAT_MONO16;
      break;
    case(Stereo8):
      alformat=AL_FORMAT_STEREO8;
      break;
    case(Stereo16):
      alformat=AL_FORMAT_STEREO16;
      break;
  }
  updater_=new NetUpdater(socket,NULL,buffername_,buffer2_->GetName(),
			  alformat,frequency,packetsize);
}

NetStream::NetStream(const NetStream &stream) : Stream((const Stream &)stream){
  // TODO: Copy/Reference etc. updater..
}

NetStream::~NetStream() {
  delete updater_;
}

NetStream &NetStream::operator=(const NetStream &stream) {
  if(&stream!=this) {
    Stream::operator=((const Stream &)stream);
    // TODO: Delete/Dereference updater..
    // TODO: Copy/Reference etc. updater..
  }
  return *this;
}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

// #define VERBOSE_DEBUG

#define LOG_TAG "Minikin"
#include <cutils/log.h>

#include "MinikinInternal.h"
#include <minikin/CmapCoverage.h>
#include <minikin/FontCollection.h>

using std::vector;

namespace android {

template <typename T>
static inline T max(T a, T b) {
    return a>b ? a : b;
}

FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
    mMaxChar(0) {
    AutoMutex _l(gMinikinLock);
    vector<uint32_t> lastChar;
    size_t nTypefaces = typefaces.size();
#ifdef VERBOSE_DEBUG
    ALOGD("nTypefaces = %d\n", nTypefaces);
#endif
    const FontStyle defaultStyle;
    for (size_t i = 0; i < nTypefaces; i++) {
        FontFamily* family = typefaces[i];
        family->RefLocked();
        FontInstance dummy;
        mInstances.push_back(dummy);  // emplace_back would be better
        FontInstance* instance = &mInstances.back();
        instance->mFamily = family;
        instance->mCoverage = new SparseBitSet;
        MinikinFont* typeface = family->getClosestMatch(defaultStyle);
#ifdef VERBOSE_DEBUG
        ALOGD("closest match = %p, family size = %d\n", typeface, family->getNumFonts());
#endif
        const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');
        size_t cmapSize = 0;
        bool ok = typeface->GetTable(cmapTag, NULL, &cmapSize);
        UniquePtr<uint8_t[]> cmapData(new uint8_t[cmapSize]);
        ok = typeface->GetTable(cmapTag, cmapData.get(), &cmapSize);
        CmapCoverage::getCoverage(*instance->mCoverage, cmapData.get(), cmapSize);
#ifdef VERBOSE_DEBUG
        ALOGD("font coverage length=%d, first ch=%x\n", instance->mCoverage->length(),
                instance->mCoverage->nextSetBit(0));
#endif
        mMaxChar = max(mMaxChar, instance->mCoverage->length());
        lastChar.push_back(instance->mCoverage->nextSetBit(0));
    }
    size_t nPages = mMaxChar >> kLogCharsPerPage;
    size_t offset = 0;
    for (size_t i = 0; i < nPages; i++) {
        Range dummy;
        mRanges.push_back(dummy);
        Range* range = &mRanges.back();
#ifdef VERBOSE_DEBUG
        ALOGD("i=%d: range start = %d\n", i, offset);
#endif
        range->start = offset;
        for (size_t j = 0; j < nTypefaces; j++) {
            if (lastChar[j] < (i + 1) << kLogCharsPerPage) {
                const FontInstance* instance = &mInstances[j];
                mInstanceVec.push_back(instance);
                offset++;
                uint32_t nextChar = instance->mCoverage->nextSetBit((i + 1) << kLogCharsPerPage);
#ifdef VERBOSE_DEBUG
                ALOGD("nextChar = %d (j = %d)\n", nextChar, j);
#endif
                lastChar[j] = nextChar;
            }
        }
        range->end = offset;
    }
}

FontCollection::~FontCollection() {
    for (size_t i = 0; i < mInstances.size(); i++) {
        delete mInstances[i].mCoverage;
        mInstances[i].mFamily->UnrefLocked();
    }
}

const FontFamily* FontCollection::getFamilyForChar(uint32_t ch) const {
    if (ch >= mMaxChar) {
        return NULL;
    }
    const Range& range = mRanges[ch >> kLogCharsPerPage];
#ifdef VERBOSE_DEBUG
    ALOGD("querying range %d:%d\n", range.start, range.end);
#endif
    for (size_t i = range.start; i < range.end; i++) {
        const FontInstance* instance = mInstanceVec[i];
        if (instance->mCoverage->get(ch)) {
            return instance->mFamily;
        }
    }
    return NULL;
}

void FontCollection::itemize(const uint16_t *string, size_t string_size, FontStyle style,
        vector<Run>* result) const {
    const FontFamily* lastFamily = NULL;
    Run* run = NULL;
    int nShorts;
    for (size_t i = 0; i < string_size; i += nShorts) {
        nShorts = 1;
        uint32_t ch = string[i];
        // sigh, decode UTF-16 by hand here
        if ((ch & 0xfc00) == 0xd800) {
            if ((i + 1) < string_size) {
                ch = 0x10000 + ((ch & 0x3ff) << 10) + (string[i + 1] & 0x3ff);
                nShorts = 2;
            }
        }
        const FontFamily* family = getFamilyForChar(ch);
        if (i == 0 || family != lastFamily) {
            Run dummy;
            result->push_back(dummy);
            run = &result->back();
            if (family == NULL) {
                run->font = NULL;  // maybe we should do something different here
            } else {
                run->font = family->getClosestMatch(style);
                run->font->RefLocked();
            }
            lastFamily = family;
            run->start = i;
        }
        run->end = i + nShorts;
    }
}

}  // namespace android
<commit_msg>Fix native crash in Latin-1 typefaces<commit_after>/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

// #define VERBOSE_DEBUG

#define LOG_TAG "Minikin"
#include <cutils/log.h>

#include "MinikinInternal.h"
#include <minikin/CmapCoverage.h>
#include <minikin/FontCollection.h>

using std::vector;

namespace android {

template <typename T>
static inline T max(T a, T b) {
    return a>b ? a : b;
}

FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
    mMaxChar(0) {
    AutoMutex _l(gMinikinLock);
    vector<uint32_t> lastChar;
    size_t nTypefaces = typefaces.size();
#ifdef VERBOSE_DEBUG
    ALOGD("nTypefaces = %d\n", nTypefaces);
#endif
    const FontStyle defaultStyle;
    for (size_t i = 0; i < nTypefaces; i++) {
        FontFamily* family = typefaces[i];
        family->RefLocked();
        FontInstance dummy;
        mInstances.push_back(dummy);  // emplace_back would be better
        FontInstance* instance = &mInstances.back();
        instance->mFamily = family;
        instance->mCoverage = new SparseBitSet;
        MinikinFont* typeface = family->getClosestMatch(defaultStyle);
#ifdef VERBOSE_DEBUG
        ALOGD("closest match = %p, family size = %d\n", typeface, family->getNumFonts());
#endif
        const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');
        size_t cmapSize = 0;
        bool ok = typeface->GetTable(cmapTag, NULL, &cmapSize);
        UniquePtr<uint8_t[]> cmapData(new uint8_t[cmapSize]);
        ok = typeface->GetTable(cmapTag, cmapData.get(), &cmapSize);
        CmapCoverage::getCoverage(*instance->mCoverage, cmapData.get(), cmapSize);
#ifdef VERBOSE_DEBUG
        ALOGD("font coverage length=%d, first ch=%x\n", instance->mCoverage->length(),
                instance->mCoverage->nextSetBit(0));
#endif
        mMaxChar = max(mMaxChar, instance->mCoverage->length());
        lastChar.push_back(instance->mCoverage->nextSetBit(0));
    }
    size_t nPages = (mMaxChar + kPageMask) >> kLogCharsPerPage;
    size_t offset = 0;
    for (size_t i = 0; i < nPages; i++) {
        Range dummy;
        mRanges.push_back(dummy);
        Range* range = &mRanges.back();
#ifdef VERBOSE_DEBUG
        ALOGD("i=%d: range start = %d\n", i, offset);
#endif
        range->start = offset;
        for (size_t j = 0; j < nTypefaces; j++) {
            if (lastChar[j] < (i + 1) << kLogCharsPerPage) {
                const FontInstance* instance = &mInstances[j];
                mInstanceVec.push_back(instance);
                offset++;
                uint32_t nextChar = instance->mCoverage->nextSetBit((i + 1) << kLogCharsPerPage);
#ifdef VERBOSE_DEBUG
                ALOGD("nextChar = %d (j = %d)\n", nextChar, j);
#endif
                lastChar[j] = nextChar;
            }
        }
        range->end = offset;
    }
}

FontCollection::~FontCollection() {
    for (size_t i = 0; i < mInstances.size(); i++) {
        delete mInstances[i].mCoverage;
        mInstances[i].mFamily->UnrefLocked();
    }
}

const FontFamily* FontCollection::getFamilyForChar(uint32_t ch) const {
    if (ch >= mMaxChar) {
        return NULL;
    }
    const Range& range = mRanges[ch >> kLogCharsPerPage];
#ifdef VERBOSE_DEBUG
    ALOGD("querying range %d:%d\n", range.start, range.end);
#endif
    for (size_t i = range.start; i < range.end; i++) {
        const FontInstance* instance = mInstanceVec[i];
        if (instance->mCoverage->get(ch)) {
            return instance->mFamily;
        }
    }
    return NULL;
}

void FontCollection::itemize(const uint16_t *string, size_t string_size, FontStyle style,
        vector<Run>* result) const {
    const FontFamily* lastFamily = NULL;
    Run* run = NULL;
    int nShorts;
    for (size_t i = 0; i < string_size; i += nShorts) {
        nShorts = 1;
        uint32_t ch = string[i];
        // sigh, decode UTF-16 by hand here
        if ((ch & 0xfc00) == 0xd800) {
            if ((i + 1) < string_size) {
                ch = 0x10000 + ((ch & 0x3ff) << 10) + (string[i + 1] & 0x3ff);
                nShorts = 2;
            }
        }
        const FontFamily* family = getFamilyForChar(ch);
        if (i == 0 || family != lastFamily) {
            Run dummy;
            result->push_back(dummy);
            run = &result->back();
            if (family == NULL) {
                run->font = NULL;  // maybe we should do something different here
            } else {
                run->font = family->getClosestMatch(style);
                run->font->RefLocked();
            }
            lastFamily = family;
            run->start = i;
        }
        run->end = i + nShorts;
    }
}

}  // namespace android
<|endoftext|>


<commit_before>/// @file
/// @author uentity
/// @date 12.01.2016
/// @brief
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include <bs/bs.h>
#include <bs/compat/messaging.h>

NAMESPACE_BEGIN(blue_sky)
NAMESPACE_BEGIN(python)

void py_bind_signal(py::module&);

namespace {
using namespace std;

// bs_slot wrapper
class py_bs_slot : public bs_slot {
public:
	using bs_slot::bs_slot;

	void execute(sp_cobj sender, int signal_code, sp_obj param) const override {
		PYBIND11_OVERLOAD_PURE(
			void,
			bs_slot,
			execute,
			std::move(sender), signal_code, std::move(param)
		);
	}
};

// bs_imessaging wrapper
// template used to flatten trampoline hierarchy -- they don't support multiple inheritance
template<typename Next = bs_imessaging>
class py_bs_imessaging : public Next {
public:
	using Next::Next;

	bool subscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD_PURE(
			bool,
			Next,
			subscribe,
			signal_code, slot
		);
	}

	bool unsubscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD_PURE(
			bool,
			Next,
			unsubscribe,
			signal_code, slot
		);
	}

	ulong num_slots(int signal_code) const override {
		PYBIND11_OVERLOAD_PURE(
			ulong,
			Next,
			num_slots,
			signal_code
		);
	}

	bool fire_signal(int signal_code, const sp_obj& param) const override {
		PYBIND11_OVERLOAD_PURE(
			bool,
			Next,
			fire_signal,
			signal_code, param
		);
	}

	std::vector< int > get_signal_list() const override {
		PYBIND11_OVERLOAD_PURE(
			std::vector< int >,
			Next,
			get_signal_list
		);
	}
};

// resulting trampoline for bs_mesagins
class py_bs_messaging : public py_bs_imessaging< py_object<bs_messaging> > {
public:
	using py_bs_imessaging<py_object<bs_messaging>>::py_bs_imessaging;

	bool subscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			subscribe,
			signal_code, slot
		);
	}

	bool unsubscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			unsubscribe,
			signal_code, slot
		);
	}

	ulong num_slots(int signal_code) const override {
		PYBIND11_OVERLOAD(
			ulong,
			bs_messaging,
			num_slots,
			signal_code
		);
	}

	bool fire_signal(int signal_code, const sp_obj& param) const override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			fire_signal,
			signal_code, param
		);
	}

	std::vector< int > get_signal_list() const override {
		PYBIND11_OVERLOAD(
			std::vector< int >,
			bs_messaging,
			get_signal_list
		);
	}

	bool add_signal(int signal_code) override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			add_signal,
			signal_code
		);
	}

	bool remove_signal(int signal_code) override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			remove_signal,
			signal_code
		);
	}
};

void slot_tester(int c, const sp_slot& slot, const sp_obj& param ) {
	slot->execute(nullptr, c, param);
}

} //eof hidden namespace

// exporting function
void py_bind_messaging(py::module& m) {
	// export bs_slot wrapper
	py::class_<
		bs_slot, py_bs_slot, std::shared_ptr<bs_slot>
	>(m, "slot")
		.def(py::init<>())
		.def("execute", &bs_slot::execute)
	;

	// DEBUG
	m.def("slot_tester", &slot_tester);

	// bs_imessaging abstract class
	py::class_<
		bs_imessaging, py_bs_imessaging<>, std::shared_ptr<bs_imessaging>
	>(m, "imessaging")
		.def("subscribe"       , &bs_imessaging::subscribe)
		.def("unsubscribe"     , &bs_imessaging::unsubscribe)
		.def("num_slots"       , &bs_imessaging::num_slots)
		.def("fire_signal"     , &bs_imessaging::fire_signal,
			"signal_code"_a, "param"_a = nullptr
		)
		.def("get_signal_list" , &bs_imessaging::get_signal_list)
	;

	// bs_messaging
	bool (bs_messaging::*add_signal_ptr)(int) = &bs_messaging::add_signal;

	py::class_<
		bs_messaging, bs_imessaging, objbase, py_bs_messaging,
		std::shared_ptr< bs_messaging >
	>(m, "messaging", py::multiple_inheritance())
		BSPY_EXPORT_DEF(bs_messaging)
		BSPY_ENABLE_PYOBJ(bs_messaging)
		.def(py::init_alias<>())
		.def(py::init_alias< bs_messaging::sig_range_t >())
		.def("subscribe"       , &bs_messaging::subscribe)
		.def("unsubscribe"     , &bs_messaging::unsubscribe)
		.def("num_slots"       , &bs_messaging::num_slots)
		.def("fire_signal"     , &bs_messaging::fire_signal,
			"signal_code"_a, "param"_a = nullptr
		)
		.def("add_signal"      , add_signal_ptr)
		.def("remove_signal"   , &bs_messaging::remove_signal)
		.def("get_signal_list" , &bs_messaging::get_signal_list)
		.def("clear"           , &bs_messaging::clear)
		.def("test_slot1", [](const bs_messaging& src, const sp_slot& slot, const sp_obj param = nullptr) {
			slot->execute(src.shared_from_this(), 42, param);
		})
	;

	py_bind_signal(m);
}

NAMESPACE_END(python)
NAMESPACE_END(blue_sky)

<commit_msg>python.bs_slot: don't fail with runtime error if Python slot is deleted<commit_after>/// @file
/// @author uentity
/// @date 12.01.2016
/// @brief
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include <bs/bs.h>
#include <bs/compat/messaging.h>

NAMESPACE_BEGIN(blue_sky)
NAMESPACE_BEGIN(python)

void py_bind_signal(py::module&);

namespace {
using namespace std;

// bs_slot wrapper
class py_bs_slot : public bs_slot {
public:
	using bs_slot::bs_slot;

	void execute(sp_cobj sender, int signal_code, sp_obj param) const override {
		// Use modified version of PYBIND11_OVERLOAD_PURE macro code
		// original implementation would fail with runtime error that pure virtual method is called
		// if no overload was found. But slot should be safe in sutuation when Python object is
		// already destroyed. In such a case just DO NOTHING and return.
		pybind11::gil_scoped_acquire gil;
		pybind11::function overload = pybind11::get_overload(static_cast<const bs_slot *>(this), "execute");
		if (overload) {
			auto o = overload(std::move(sender), signal_code, std::move(param));
			if (pybind11::detail::cast_is_temporary_value_reference<void>::value) {
				static pybind11::detail::overload_caster_t<void> caster;
				return pybind11::detail::cast_ref<void>(std::move(o), caster);
			}
			else return pybind11::detail::cast_safe<void>(std::move(o));
		}
		//PYBIND11_OVERLOAD_PURE(
		//	void,
		//	bs_slot,
		//	execute,
		//	std::move(sender), signal_code, std::move(param)
		//);
	}
};

// bs_imessaging wrapper
// template used to flatten trampoline hierarchy -- they don't support multiple inheritance
template<typename Next = bs_imessaging>
class py_bs_imessaging : public Next {
public:
	using Next::Next;

	bool subscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD_PURE(
			bool,
			Next,
			subscribe,
			signal_code, slot
		);
	}

	bool unsubscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD_PURE(
			bool,
			Next,
			unsubscribe,
			signal_code, slot
		);
	}

	ulong num_slots(int signal_code) const override {
		PYBIND11_OVERLOAD_PURE(
			ulong,
			Next,
			num_slots,
			signal_code
		);
	}

	bool fire_signal(int signal_code, const sp_obj& param) const override {
		PYBIND11_OVERLOAD_PURE(
			bool,
			Next,
			fire_signal,
			signal_code, param
		);
	}

	std::vector< int > get_signal_list() const override {
		PYBIND11_OVERLOAD_PURE(
			std::vector< int >,
			Next,
			get_signal_list
		);
	}
};

// resulting trampoline for bs_mesagins
class py_bs_messaging : public py_bs_imessaging< py_object<bs_messaging> > {
public:
	using py_bs_imessaging<py_object<bs_messaging>>::py_bs_imessaging;

	bool subscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			subscribe,
			signal_code, slot
		);
	}

	bool unsubscribe(int signal_code, const sp_slot& slot) const override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			unsubscribe,
			signal_code, slot
		);
	}

	ulong num_slots(int signal_code) const override {
		PYBIND11_OVERLOAD(
			ulong,
			bs_messaging,
			num_slots,
			signal_code
		);
	}

	bool fire_signal(int signal_code, const sp_obj& param) const override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			fire_signal,
			signal_code, param
		);
	}

	std::vector< int > get_signal_list() const override {
		PYBIND11_OVERLOAD(
			std::vector< int >,
			bs_messaging,
			get_signal_list
		);
	}

	bool add_signal(int signal_code) override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			add_signal,
			signal_code
		);
	}

	bool remove_signal(int signal_code) override {
		PYBIND11_OVERLOAD(
			bool,
			bs_messaging,
			remove_signal,
			signal_code
		);
	}
};

void slot_tester(int c, const sp_slot& slot, const sp_obj& param ) {
	slot->execute(nullptr, c, param);
}

} //eof hidden namespace

// exporting function
void py_bind_messaging(py::module& m) {
	// export bs_slot wrapper
	py::class_<
		bs_slot, py_bs_slot, std::shared_ptr<bs_slot>
	>(m, "slot")
		.def(py::init<>())
		.def("execute", &bs_slot::execute)
	;

	// DEBUG
	m.def("slot_tester", &slot_tester);

	// bs_imessaging abstract class
	py::class_<
		bs_imessaging, py_bs_imessaging<>, std::shared_ptr<bs_imessaging>
	>(m, "imessaging")
		.def("subscribe"       , &bs_imessaging::subscribe)
		.def("unsubscribe"     , &bs_imessaging::unsubscribe)
		.def("num_slots"       , &bs_imessaging::num_slots)
		.def("fire_signal"     , &bs_imessaging::fire_signal,
			"signal_code"_a, "param"_a = nullptr
		)
		.def("get_signal_list" , &bs_imessaging::get_signal_list)
	;

	// bs_messaging
	bool (bs_messaging::*add_signal_ptr)(int) = &bs_messaging::add_signal;

	py::class_<
		bs_messaging, bs_imessaging, objbase, py_bs_messaging,
		std::shared_ptr< bs_messaging >
	>(m, "messaging", py::multiple_inheritance())
		BSPY_EXPORT_DEF(bs_messaging)
		BSPY_ENABLE_PYOBJ(bs_messaging)
		.def(py::init_alias<>())
		.def(py::init_alias< bs_messaging::sig_range_t >())
		.def("subscribe"       , &bs_messaging::subscribe)
		.def("unsubscribe"     , &bs_messaging::unsubscribe)
		.def("num_slots"       , &bs_messaging::num_slots)
		.def("fire_signal"     , &bs_messaging::fire_signal,
			"signal_code"_a, "param"_a = nullptr
		)
		.def("add_signal"      , add_signal_ptr)
		.def("remove_signal"   , &bs_messaging::remove_signal)
		.def("get_signal_list" , &bs_messaging::get_signal_list)
		.def("clear"           , &bs_messaging::clear)
		.def("test_slot1", [](const bs_messaging& src, const sp_slot& slot, const sp_obj param = nullptr) {
			slot->execute(src.shared_from_this(), 42, param);
		})
	;

	py_bind_signal(m);
}

NAMESPACE_END(python)
NAMESPACE_END(blue_sky)

<|endoftext|>


<commit_before>/*
    Copyright (C) 2013 Timo Linna. All Rights Reserved.
*/
#include "cnuodb.h"
#include "NuoDB.h"
#include <algorithm>
#include <cstring>
#include <string>

using namespace NuoDB;

struct nuodb {
    Connection *conn;
    std::string error;
};

static int setError(struct nuodb *db, SQLException &e) {
    db->error.assign(e.getText());
    return e.getSqlcode();
}

static int closeDb(struct nuodb *db) {
    if (db->conn) {
        try {
            db->conn->close();
            db->conn = 0;
        } catch (SQLException &e) {
            return setError(db, e);
        }
    }
    return 0;
}

void nuodb_init(struct nuodb **db) {
    *db = new struct nuodb;
    (*db)->conn = 0;
}

const char *nuodb_error(const struct nuodb *db) {
    return db ? db->error.c_str() : "null db";
}

int nuodb_open(struct nuodb *db, const char *database, const char *username,
               const char *password, const char *schema, const char *timezone) {
    closeDb(db);
    Connection *conn = 0;
    try {
        conn = Connection::create();
        Properties *props = conn->allocProperties(); // TODO: freed on conn->close()?
        props->putValue("user", username);
        props->putValue("password", password);
        if (schema && std::strlen(schema) > 0) {
            props->putValue("schema", schema);
        }
        if (timezone && std::strlen(timezone) > 0) {
            props->putValue("timezone", timezone);
        }
        conn->openDatabase(database, props);
        conn->setAutoCommit(true); // enforce autocommit by default
        db->conn = conn;
        return 0;
    } catch (SQLException &e) {
        if (conn) {
            conn->close();
        }
        return setError(db, e);
    }
}

int nuodb_close(struct nuodb **db) {
    int rc = 0;
    if (db && *db) {
        rc = closeDb(*db);
        delete (*db);
        *db = 0;
    }
    return rc;
}

int nuodb_autocommit(struct nuodb *db, int *state) {
    try {
        *state = db->conn->getAutoCommit();
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_autocommit_set(struct nuodb *db, int state) {
    try {
        db->conn->setAutoCommit(!!state);
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_commit(struct nuodb *db) {
    try {
        db->conn->commit();
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_rollback(struct nuodb *db) {
    try {
        db->conn->rollback();
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_execute(struct nuodb *db, const char *sql,
                  int64_t *rows_affected, int64_t *last_insert_id) {
    Statement *stmt = 0;
    ResultSet *resultSet = 0;
    try {
        stmt = db->conn->createStatement();
        int64_t lastInsertId = 0;
        int updateCount = stmt->executeUpdate(sql, RETURN_GENERATED_KEYS);
        if (updateCount > 0) {
            resultSet = stmt->getGeneratedKeys();
            if (resultSet->getMetaData()->getColumnCount() > 0) {
                while (resultSet->next()) {
                    // TODO find out how to read the last id first
                }
                lastInsertId = resultSet->getLong(1);
            }
            resultSet->close();
            resultSet = 0;
        }
        stmt->close();
        *rows_affected = updateCount;
        *last_insert_id = lastInsertId;
        return 0;
    } catch (SQLException &e) {
        if (resultSet) {
            resultSet->close();
        }
        if (stmt) {
            stmt->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_prepare(struct nuodb *db, const char *sql,
                            struct nuodb_statement **st, int *parameter_count) {
    PreparedStatement *stmt = 0;
    try {
        stmt = db->conn->prepareStatement(sql, RETURN_GENERATED_KEYS);
        *parameter_count = stmt->getParameterMetaData()->getParameterCount();
        *st = reinterpret_cast<struct nuodb_statement *>(stmt);
        return 0;
    } catch (SQLException &e) {
        if (stmt) {
            stmt->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_bind(struct nuodb *db, struct nuodb_statement *st,
                         struct nuodb_value parameters[]) {
    PreparedStatement *stmt = reinterpret_cast<PreparedStatement *>(st);
    try {
        int parameterCount = stmt->getParameterMetaData()->getParameterCount();
        for (int i=0; i < parameterCount; ++i) {
            int parameterIndex = i+1;
            switch (parameters[i].vt) {
                case NUODB_TYPE_NULL:
                    stmt->setNull(parameterIndex, NUOSQL_NULL);
                    break;
                case NUODB_TYPE_INT64:
                    stmt->setLong(parameterIndex, parameters[i].i64);
                    break;
                case NUODB_TYPE_FLOAT64: {
                    union {
                        int64_t i64;
                        double float64;
                    } value = { parameters[i].i64 };
                    stmt->setDouble(parameterIndex, value.float64);
                    break;
                }
                case NUODB_TYPE_BOOL:
                    stmt->setBoolean(parameterIndex, !!parameters[i].i64);
                    break;
                case NUODB_TYPE_STRING: {
                    union {
                        int64_t i64;
                        const char *bytes;
                    } value = { parameters[i].i64 };
                    // Extra conversion due to missing length param from the setString API
                    std::string str(value.bytes, parameters[i].i32);
                    stmt->setString(parameterIndex, str.c_str());
                    break;
                }
                case NUODB_TYPE_BYTES: {
                    union {
                        int64_t i64;
                        const unsigned char *bytes;
                    } value = { parameters[i].i64 };
                    stmt->setBytes(parameterIndex, parameters[i].i32, value.bytes);
                    break;
                }
                case NUODB_TYPE_TIME: {
                    int64_t seconds = parameters[i].i64;
                    int32_t nanos = parameters[i].i32;
                    SqlTimestamp ts(seconds, nanos);
                    stmt->setTimestamp(parameterIndex, &ts);
                    break;
                }
            }
        }
        return 0;
    } catch  (SQLException &e) {
        if (stmt) {
            stmt->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_execute(struct nuodb *db, struct nuodb_statement *st,
                            struct nuodb_resultset **rs, int *column_count, int64_t *rows_affected) {
    ResultSet *resultSet = 0;
    PreparedStatement *stmt = reinterpret_cast<PreparedStatement *>(st);
    try {
        int updateCount;
        bool hasResults = stmt->execute();
        if (hasResults) {
            resultSet = stmt->getResultSet();
            updateCount = 0;
        } else {
            resultSet = stmt->getGeneratedKeys();
            // NuoDB uses -1 as a flag for zero-rows-affected
            updateCount = std::max(0, stmt->getUpdateCount());
        }
        *column_count = resultSet->getMetaData()->getColumnCount();
        *rows_affected = updateCount;
        *rs = reinterpret_cast<struct nuodb_resultset *>(resultSet);
        return 0;
    } catch (SQLException &e) {
        if (resultSet) {
            resultSet->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_close(struct nuodb *db, struct nuodb_statement **st) {
    try {
        if (st && *st) {
            PreparedStatement *stmt = reinterpret_cast<PreparedStatement *>(*st);
            stmt->close();
            *st = 0;
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_last_insert_id(struct nuodb *db, struct nuodb_resultset *rs,
                                   int64_t *last_insert_id) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        int64_t lastInsertId = 0;
        if (resultSet->getMetaData()->getColumnCount() > 0) {
            while (resultSet->next()) {
                // TODO find out how to read the last id first
            }
            lastInsertId = resultSet->getLong(1);
        }
        *last_insert_id = lastInsertId;
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_column_names(struct nuodb *db, struct nuodb_resultset *rs,
                                 struct nuodb_value names[]) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        ResultSetMetaData *resultSetMetaData = resultSet->getMetaData();
        int columnCount = resultSetMetaData->getColumnCount();
        for (int i=0; i < columnCount; ++i) {
            int columnIndex = i+1;
            union {
                const char *string;
                int64_t i64;
            } value = { resultSetMetaData->getColumnLabel(columnIndex) };
            names[i].i64 = value.i64;
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_next(struct nuodb *db, struct nuodb_resultset *rs,
                         int *has_values, int *bytes_count, struct nuodb_value values[]) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        int bytesCount = 0;
        *has_values = resultSet->next();
        if (*has_values) {
            ResultSetMetaData *resultSetMetaData = resultSet->getMetaData();
            int columnCount = resultSetMetaData->getColumnCount();
            for (int i=0; i < columnCount; ++i) {
                int64_t i64 = 0;
                int32_t i32 = 0;
                enum nuodb_value_type vt = NUODB_TYPE_NULL;
                int columnIndex = i+1;
                switch (resultSetMetaData->getColumnType(columnIndex)) {
                    case NUOSQL_NULL:
                        vt = NUODB_TYPE_NULL;
                        break;
                    case NUOSQL_TINYINT:
                    case NUOSQL_SMALLINT:
                    case NUOSQL_INTEGER:
                    case NUOSQL_BIGINT:
                        if (resultSetMetaData->getScale(columnIndex) == 0) {
                            i64 = resultSet->getLong(columnIndex);
                            if (!resultSet->wasNull()) {
                                vt = NUODB_TYPE_INT64;
                            }
                            break;
                        }
                        // fallthrough; must be fetched as a string
                    case NUOSQL_NUMERIC:
                    case NUOSQL_DECIMAL: {
                        const char *str = resultSet->getString(columnIndex);
                        if (str && !resultSet->wasNull()) {
                            vt = NUODB_TYPE_BYTES; // strings are returned as bytes
                            i32 = std::strlen(str);
                            bytesCount += i32;
                        }
                        break;
                    }
                    case NUOSQL_FLOAT:
                    case NUOSQL_DOUBLE: {
                        union {
                            double float64;
                            int64_t i64;
                        } value = { resultSet->getDouble(columnIndex) };
                        if (!resultSet->wasNull()) {
                            vt = NUODB_TYPE_FLOAT64;
                            i64 = value.i64;
                        }
                        break;
                    }
                    case NUOSQL_BIT:
                    case NUOSQL_BOOLEAN:
                        i64 = resultSet->getBoolean(columnIndex);
                        if (!resultSet->wasNull()) {
                            vt = NUODB_TYPE_BOOL;
                        }
                        break;
                    case NUOSQL_DATE:
                    case NUOSQL_TIME:
                    case NUOSQL_TIMESTAMP: {
                        Timestamp *ts = resultSet->getTimestamp(columnIndex);
                        if (ts && !resultSet->wasNull()) {
                            vt = NUODB_TYPE_TIME;
                            i64 = ts->getSeconds();
                            i32 = ts->getNanos();
                        }
                        break;
                    }
                    default: {
                        const Bytes b = resultSet->getBytes(columnIndex);
                        if (!resultSet->wasNull()) {
                            vt = NUODB_TYPE_BYTES;
                            i32 = b.length;
                            bytesCount += i32;
                        }
                        break;
                    }
                }
                values[i].i64 = i64;
                values[i].i32 = i32;
                values[i].vt = vt;
            }
        }
        *bytes_count = bytesCount;
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_bytes(struct nuodb *db, struct nuodb_resultset *rs, unsigned char *bytes) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        ResultSetMetaData *resultSetMetaData = resultSet->getMetaData();
        int columnCount = resultSetMetaData->getColumnCount();
        for (int i=0; i < columnCount; ++i) {
            int columnIndex = i+1;
            switch (resultSetMetaData->getColumnType(columnIndex)) {
                case NUOSQL_NULL:
                case NUOSQL_FLOAT:
                case NUOSQL_DOUBLE:
                case NUOSQL_BIT:
                case NUOSQL_BOOLEAN:
                case NUOSQL_DATE:
                case NUOSQL_TIME:
                case NUOSQL_TIMESTAMP:
                    break; // skip
                case NUOSQL_TINYINT:
                case NUOSQL_SMALLINT:
                case NUOSQL_INTEGER:
                case NUOSQL_BIGINT:
                    if (resultSetMetaData->getScale(columnIndex) == 0) {
                        break; // skip
                    }
                    // fallthrough; must be fetched as a string
                case NUOSQL_NUMERIC:
                case NUOSQL_DECIMAL: {
                    const char *str = resultSet->getString(columnIndex);
                    if (str && !resultSet->wasNull()) {
                        size_t length = std::strlen(str);
                        std::memcpy(bytes, str, length);
                        bytes += length;
                    }
                    break;
                }
                default: {
                    const Bytes b = resultSet->getBytes(columnIndex);
                    if (!resultSet->wasNull()) {
                        std::memcpy(bytes, b.data, b.length);
                        bytes += b.length;
                    }
                    break;
                }
            }
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_close(struct nuodb *db, struct nuodb_resultset **rs) {
    try {
        if (rs && *rs) {
            ResultSet *resultSet = reinterpret_cast<ResultSet *>(*rs);
            resultSet->close();
            *rs = 0;
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}
<commit_msg>Ensure rows_affected >= 0 also for nuodb_execute<commit_after>/*
    Copyright (C) 2013 Timo Linna. All Rights Reserved.
*/
#include "cnuodb.h"
#include "NuoDB.h"
#include <algorithm>
#include <cstring>
#include <string>

using namespace NuoDB;

struct nuodb {
    Connection *conn;
    std::string error;
};

static int setError(struct nuodb *db, SQLException &e) {
    db->error.assign(e.getText());
    return e.getSqlcode();
}

static int closeDb(struct nuodb *db) {
    if (db->conn) {
        try {
            db->conn->close();
            db->conn = 0;
        } catch (SQLException &e) {
            return setError(db, e);
        }
    }
    return 0;
}

void nuodb_init(struct nuodb **db) {
    *db = new struct nuodb;
    (*db)->conn = 0;
}

const char *nuodb_error(const struct nuodb *db) {
    return db ? db->error.c_str() : "null db";
}

int nuodb_open(struct nuodb *db, const char *database, const char *username,
               const char *password, const char *schema, const char *timezone) {
    closeDb(db);
    Connection *conn = 0;
    try {
        conn = Connection::create();
        Properties *props = conn->allocProperties(); // TODO: freed on conn->close()?
        props->putValue("user", username);
        props->putValue("password", password);
        if (schema && std::strlen(schema) > 0) {
            props->putValue("schema", schema);
        }
        if (timezone && std::strlen(timezone) > 0) {
            props->putValue("timezone", timezone);
        }
        conn->openDatabase(database, props);
        conn->setAutoCommit(true); // enforce autocommit by default
        db->conn = conn;
        return 0;
    } catch (SQLException &e) {
        if (conn) {
            conn->close();
        }
        return setError(db, e);
    }
}

int nuodb_close(struct nuodb **db) {
    int rc = 0;
    if (db && *db) {
        rc = closeDb(*db);
        delete (*db);
        *db = 0;
    }
    return rc;
}

int nuodb_autocommit(struct nuodb *db, int *state) {
    try {
        *state = db->conn->getAutoCommit();
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_autocommit_set(struct nuodb *db, int state) {
    try {
        db->conn->setAutoCommit(!!state);
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_commit(struct nuodb *db) {
    try {
        db->conn->commit();
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_rollback(struct nuodb *db) {
    try {
        db->conn->rollback();
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_execute(struct nuodb *db, const char *sql,
                  int64_t *rows_affected, int64_t *last_insert_id) {
    Statement *stmt = 0;
    ResultSet *resultSet = 0;
    try {
        stmt = db->conn->createStatement();
        int64_t lastInsertId = 0;
        int updateCount = stmt->executeUpdate(sql, RETURN_GENERATED_KEYS);
        if (updateCount > 0) {
            resultSet = stmt->getGeneratedKeys();
            if (resultSet->getMetaData()->getColumnCount() > 0) {
                while (resultSet->next()) {
                    // TODO find out how to read the last id first
                }
                lastInsertId = resultSet->getLong(1);
            }
            resultSet->close();
            resultSet = 0;
        }
        stmt->close();
        // NuoDB uses -1 as a flag for zero-rows-affected
        *rows_affected = std::max(0, updateCount);
        *last_insert_id = lastInsertId;
        return 0;
    } catch (SQLException &e) {
        if (resultSet) {
            resultSet->close();
        }
        if (stmt) {
            stmt->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_prepare(struct nuodb *db, const char *sql,
                            struct nuodb_statement **st, int *parameter_count) {
    PreparedStatement *stmt = 0;
    try {
        stmt = db->conn->prepareStatement(sql, RETURN_GENERATED_KEYS);
        *parameter_count = stmt->getParameterMetaData()->getParameterCount();
        *st = reinterpret_cast<struct nuodb_statement *>(stmt);
        return 0;
    } catch (SQLException &e) {
        if (stmt) {
            stmt->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_bind(struct nuodb *db, struct nuodb_statement *st,
                         struct nuodb_value parameters[]) {
    PreparedStatement *stmt = reinterpret_cast<PreparedStatement *>(st);
    try {
        int parameterCount = stmt->getParameterMetaData()->getParameterCount();
        for (int i=0; i < parameterCount; ++i) {
            int parameterIndex = i+1;
            switch (parameters[i].vt) {
                case NUODB_TYPE_NULL:
                    stmt->setNull(parameterIndex, NUOSQL_NULL);
                    break;
                case NUODB_TYPE_INT64:
                    stmt->setLong(parameterIndex, parameters[i].i64);
                    break;
                case NUODB_TYPE_FLOAT64: {
                    union {
                        int64_t i64;
                        double float64;
                    } value = { parameters[i].i64 };
                    stmt->setDouble(parameterIndex, value.float64);
                    break;
                }
                case NUODB_TYPE_BOOL:
                    stmt->setBoolean(parameterIndex, !!parameters[i].i64);
                    break;
                case NUODB_TYPE_STRING: {
                    union {
                        int64_t i64;
                        const char *bytes;
                    } value = { parameters[i].i64 };
                    // Extra conversion due to missing length param from the setString API
                    std::string str(value.bytes, parameters[i].i32);
                    stmt->setString(parameterIndex, str.c_str());
                    break;
                }
                case NUODB_TYPE_BYTES: {
                    union {
                        int64_t i64;
                        const unsigned char *bytes;
                    } value = { parameters[i].i64 };
                    stmt->setBytes(parameterIndex, parameters[i].i32, value.bytes);
                    break;
                }
                case NUODB_TYPE_TIME: {
                    int64_t seconds = parameters[i].i64;
                    int32_t nanos = parameters[i].i32;
                    SqlTimestamp ts(seconds, nanos);
                    stmt->setTimestamp(parameterIndex, &ts);
                    break;
                }
            }
        }
        return 0;
    } catch  (SQLException &e) {
        if (stmt) {
            stmt->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_execute(struct nuodb *db, struct nuodb_statement *st,
                            struct nuodb_resultset **rs, int *column_count, int64_t *rows_affected) {
    ResultSet *resultSet = 0;
    PreparedStatement *stmt = reinterpret_cast<PreparedStatement *>(st);
    try {
        int updateCount;
        bool hasResults = stmt->execute();
        if (hasResults) {
            resultSet = stmt->getResultSet();
            updateCount = 0;
        } else {
            resultSet = stmt->getGeneratedKeys();
            updateCount = stmt->getUpdateCount();
        }
        *column_count = resultSet->getMetaData()->getColumnCount();
        *rows_affected = std::max(0, updateCount);
        *rs = reinterpret_cast<struct nuodb_resultset *>(resultSet);
        return 0;
    } catch (SQLException &e) {
        if (resultSet) {
            resultSet->close();
        }
        return setError(db, e);
    }
}

int nuodb_statement_close(struct nuodb *db, struct nuodb_statement **st) {
    try {
        if (st && *st) {
            PreparedStatement *stmt = reinterpret_cast<PreparedStatement *>(*st);
            stmt->close();
            *st = 0;
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_last_insert_id(struct nuodb *db, struct nuodb_resultset *rs,
                                   int64_t *last_insert_id) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        int64_t lastInsertId = 0;
        if (resultSet->getMetaData()->getColumnCount() > 0) {
            while (resultSet->next()) {
                // TODO find out how to read the last id first
            }
            lastInsertId = resultSet->getLong(1);
        }
        *last_insert_id = lastInsertId;
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_column_names(struct nuodb *db, struct nuodb_resultset *rs,
                                 struct nuodb_value names[]) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        ResultSetMetaData *resultSetMetaData = resultSet->getMetaData();
        int columnCount = resultSetMetaData->getColumnCount();
        for (int i=0; i < columnCount; ++i) {
            int columnIndex = i+1;
            union {
                const char *string;
                int64_t i64;
            } value = { resultSetMetaData->getColumnLabel(columnIndex) };
            names[i].i64 = value.i64;
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_next(struct nuodb *db, struct nuodb_resultset *rs,
                         int *has_values, int *bytes_count, struct nuodb_value values[]) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        int bytesCount = 0;
        *has_values = resultSet->next();
        if (*has_values) {
            ResultSetMetaData *resultSetMetaData = resultSet->getMetaData();
            int columnCount = resultSetMetaData->getColumnCount();
            for (int i=0; i < columnCount; ++i) {
                int64_t i64 = 0;
                int32_t i32 = 0;
                enum nuodb_value_type vt = NUODB_TYPE_NULL;
                int columnIndex = i+1;
                switch (resultSetMetaData->getColumnType(columnIndex)) {
                    case NUOSQL_NULL:
                        vt = NUODB_TYPE_NULL;
                        break;
                    case NUOSQL_TINYINT:
                    case NUOSQL_SMALLINT:
                    case NUOSQL_INTEGER:
                    case NUOSQL_BIGINT:
                        if (resultSetMetaData->getScale(columnIndex) == 0) {
                            i64 = resultSet->getLong(columnIndex);
                            if (!resultSet->wasNull()) {
                                vt = NUODB_TYPE_INT64;
                            }
                            break;
                        }
                        // fallthrough; must be fetched as a string
                    case NUOSQL_NUMERIC:
                    case NUOSQL_DECIMAL: {
                        const char *str = resultSet->getString(columnIndex);
                        if (str && !resultSet->wasNull()) {
                            vt = NUODB_TYPE_BYTES; // strings are returned as bytes
                            i32 = std::strlen(str);
                            bytesCount += i32;
                        }
                        break;
                    }
                    case NUOSQL_FLOAT:
                    case NUOSQL_DOUBLE: {
                        union {
                            double float64;
                            int64_t i64;
                        } value = { resultSet->getDouble(columnIndex) };
                        if (!resultSet->wasNull()) {
                            vt = NUODB_TYPE_FLOAT64;
                            i64 = value.i64;
                        }
                        break;
                    }
                    case NUOSQL_BIT:
                    case NUOSQL_BOOLEAN:
                        i64 = resultSet->getBoolean(columnIndex);
                        if (!resultSet->wasNull()) {
                            vt = NUODB_TYPE_BOOL;
                        }
                        break;
                    case NUOSQL_DATE:
                    case NUOSQL_TIME:
                    case NUOSQL_TIMESTAMP: {
                        Timestamp *ts = resultSet->getTimestamp(columnIndex);
                        if (ts && !resultSet->wasNull()) {
                            vt = NUODB_TYPE_TIME;
                            i64 = ts->getSeconds();
                            i32 = ts->getNanos();
                        }
                        break;
                    }
                    default: {
                        const Bytes b = resultSet->getBytes(columnIndex);
                        if (!resultSet->wasNull()) {
                            vt = NUODB_TYPE_BYTES;
                            i32 = b.length;
                            bytesCount += i32;
                        }
                        break;
                    }
                }
                values[i].i64 = i64;
                values[i].i32 = i32;
                values[i].vt = vt;
            }
        }
        *bytes_count = bytesCount;
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_bytes(struct nuodb *db, struct nuodb_resultset *rs, unsigned char *bytes) {
    ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs);
    try {
        ResultSetMetaData *resultSetMetaData = resultSet->getMetaData();
        int columnCount = resultSetMetaData->getColumnCount();
        for (int i=0; i < columnCount; ++i) {
            int columnIndex = i+1;
            switch (resultSetMetaData->getColumnType(columnIndex)) {
                case NUOSQL_NULL:
                case NUOSQL_FLOAT:
                case NUOSQL_DOUBLE:
                case NUOSQL_BIT:
                case NUOSQL_BOOLEAN:
                case NUOSQL_DATE:
                case NUOSQL_TIME:
                case NUOSQL_TIMESTAMP:
                    break; // skip
                case NUOSQL_TINYINT:
                case NUOSQL_SMALLINT:
                case NUOSQL_INTEGER:
                case NUOSQL_BIGINT:
                    if (resultSetMetaData->getScale(columnIndex) == 0) {
                        break; // skip
                    }
                    // fallthrough; must be fetched as a string
                case NUOSQL_NUMERIC:
                case NUOSQL_DECIMAL: {
                    const char *str = resultSet->getString(columnIndex);
                    if (str && !resultSet->wasNull()) {
                        size_t length = std::strlen(str);
                        std::memcpy(bytes, str, length);
                        bytes += length;
                    }
                    break;
                }
                default: {
                    const Bytes b = resultSet->getBytes(columnIndex);
                    if (!resultSet->wasNull()) {
                        std::memcpy(bytes, b.data, b.length);
                        bytes += b.length;
                    }
                    break;
                }
            }
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}

int nuodb_resultset_close(struct nuodb *db, struct nuodb_resultset **rs) {
    try {
        if (rs && *rs) {
            ResultSet *resultSet = reinterpret_cast<ResultSet *>(*rs);
            resultSet->close();
            *rs = 0;
        }
        return 0;
    } catch (SQLException &e) {
        return setError(db, e);
    }
}
<|endoftext|>


<commit_before>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "\n*Unknown command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
//  std::string input;

//  struct timeval timeout;
  fd_set read_set;
//  int file_desc = 0;
  int result;
  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

  char stdin_buffer[kBufferSize];
  memset(&stdin_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  std::cout << ">" << std::flush;

  std::string tmp;

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        int read_stdin_size = read(STDIN_FILENO, stdin_buffer, kBufferSize);

        if (read_stdin_size != 0) {
          if (stdin_buffer[0] == '/') {
            ProcessInput(stdin_buffer);
          } else {
            // Send chat messages
            StripChar(stdin_buffer, '\n');
            RequestSay(stdin_buffer);
            std::cout << ">" << stdin_buffer << std::flush;
          }
        }

        memset(&stdin_buffer, 0, kBufferSize);
      } // end of if STDIN

      if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data
        int read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          // TODO capture user input, store, clean input, then print buffer, afterward replace input
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              struct text_say say;
              memcpy(&say, receive_buffer, sizeof(struct text_say));
              std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
              std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
              std::cout << ">" << stdin_buffer << std::flush;
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<commit_msg>print to check stdin if<commit_after>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "\n*Unknown command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
//  std::string input;

//  struct timeval timeout;
  fd_set read_set;
//  int file_desc = 0;
  int result;
  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

  char stdin_buffer[kBufferSize];
  memset(&stdin_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  std::cout << ">" << std::flush;

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        std::cout << "entering if STDIN" << std::endl;

        int read_stdin_size = read(STDIN_FILENO, stdin_buffer, kBufferSize);

        std::cout << "after read STDIN" << std::endl;

        if (read_stdin_size != 0) {
          if (stdin_buffer[0] == '/') {
            ProcessInput(stdin_buffer);
          } else {
            // Send chat messages
            StripChar(stdin_buffer, '\n');
            RequestSay(stdin_buffer);
          }
        }

        memset(&stdin_buffer, 0, kBufferSize);
      } // end of if STDIN_FILENO

      if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data
        int read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          // TODO capture user input, store, clean input, then print buffer, afterward replace input
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              struct text_say say;
              memcpy(&say, receive_buffer, sizeof(struct text_say));
              std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
              std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
              std::cout << ">" << std::flush;
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<|endoftext|>


<commit_before>#include "kernel.h"
#include "coverage.h"
#include "numericrange.h"
#include "numericdomain.h"
#include "columndefinition.h"
#include "table.h"
#include "attributerecord.h"
#include "polygon.h"
#include "geometry.h"
#include "feature.h"
#include "factory.h"
#include "abstractfactory.h"
#include "featurefactory.h"
#include "featurecoverage.h"

using namespace Ilwis;

FeatureCoverage::FeatureCoverage() : _featureTypes(itUNKNOWN),_featureFactory(0)
{
    _featureInfo.resize(3);
    _featureInfo[0]._count =  _featureInfo[1]._count =  _featureInfo[2]._count = 0;
}

FeatureCoverage::FeatureCoverage(const Resource& resource) : Coverage(resource),_featureTypes(itUNKNOWN),_featureFactory(0)
{
    _featureInfo.resize(3);
    _featureInfo[0]._count =  _featureInfo[1]._count =  _featureInfo[2]._count = 0;
}

IlwisTypes FeatureCoverage::featureTypes() const
{
    return _featureTypes;
}

void FeatureCoverage::featureTypes(IlwisTypes types)
{
    _featureTypes = types;
}

SPFeatureI FeatureCoverage::newFeature(const Geometry& geom) {
    Locker lock(_mutex);
    SPFeatureI newfeature = createNewFeature(geom.ilwisType());
    if (newfeature != nullptr)
        newfeature->set(geom);
    return newfeature;
}

SPFeatureI FeatureCoverage::newFeatureFrom(const SPFeatureI& existingFeature, const ICoordinateSystem& csySource) {
    Locker lock(_mutex);

    SPFeatureI newfeature = createNewFeature(existingFeature->ilwisType());
    if (newfeature == nullptr)
        return newfeature;

    for(int i=0; i < existingFeature->trackSize(); ++i){
          Geometry geom = existingFeature->geometry().transform(coordinateSystem(), csySource);
          newfeature->set(geom, i);
    }
    return newfeature;
}

SPFeatureI FeatureCoverage::createNewFeature(IlwisTypes tp) {
    if ( isReadOnly())
        return SPFeatureI();
    changed(true);

    _featureTypes |= tp;
    if ( _featureFactory == 0) {
        _featureFactory = kernel()->factory<FeatureFactory>("FeatureFactory","ilwis");
    }
    _record.reset(new AttributeRecord(attributeTable(),FEATUREIDCOLUMN ));

    CreateFeature create = _featureFactory->getCreator("feature");
    IFeatureCoverage fcoverage;
    fcoverage.set(this);
    SPFeatureI newFeature(create(this));

    _record.reset(new AttributeRecord(attributeTable(),FEATUREIDCOLUMN ));
    quint32 colIndex = _record->columnIndex(FEATUREIDCOLUMN);
    if ( colIndex == iUNDEF) {
        ERROR1(ERR_NO_INITIALIZED_1, TR("attribute table"));
        return SPFeatureI();
    }
    _record->cellByRecord(_features.size(), colIndex, newFeature->featureid(), -1);
    _features.push_back(newFeature);
    quint32 cnt = featureCount(newFeature->ilwisType());
    setFeatureCount(newFeature->ilwisType(),++cnt );
    return _features.back();
}

void FeatureCoverage::setFeatureCount(IlwisTypes types, quint32 cnt)
{
    Locker lock(_mutex2);
     _featureTypes |= types;
    switch(types){
    case itPOINT:
        _featureInfo[0]._count = cnt;break;
    case itLINE:
        _featureInfo[1]._count = cnt; break;
    case itPOLYGON:
        _featureInfo[2]._count = cnt; break;
    }
}

IlwisTypes FeatureCoverage::ilwisType() const
{
    return itFEATURE;
}

FeatureCoverage *FeatureCoverage::copy()
{
    FeatureCoverage *fcov = new FeatureCoverage();
    copyTo(fcov);
    return fcov;
}

QSharedPointer<AttributeRecord> FeatureCoverage::record() const
{
    return _record;
}

void FeatureCoverage::copyTo(IlwisObject *obj)
{
    Coverage::copyTo(obj);
    FeatureCoverage *fcov = static_cast<FeatureCoverage *>(obj);
    fcov->_featureTypes = _featureTypes;
    fcov->_featureInfo = _featureInfo;
    fcov->_features = _features;
}

quint32 FeatureCoverage::featureCount(IlwisTypes types, int ) const
{
    switch(types){
    case itPOINT:
        return _featureInfo[0]._count;break;
    case itLINE:
        return _featureInfo[1]._count; break;
    case itPOLYGON:
        return _featureInfo[2]._count; break;
    default:
        return _featureInfo[0]._count + _featureInfo[1]._count + _featureInfo[2]._count;

    }
    return 0;
}

//-----------------------------------------------------------------

<commit_msg>correct type is now passed to the count method; at that moment the featurecount is not yet upped so the type will be undefined for the first feature<commit_after>#include "kernel.h"
#include "coverage.h"
#include "numericrange.h"
#include "numericdomain.h"
#include "columndefinition.h"
#include "table.h"
#include "attributerecord.h"
#include "polygon.h"
#include "geometry.h"
#include "feature.h"
#include "factory.h"
#include "abstractfactory.h"
#include "featurefactory.h"
#include "featurecoverage.h"

using namespace Ilwis;

FeatureCoverage::FeatureCoverage() : _featureTypes(itUNKNOWN),_featureFactory(0)
{
    _featureInfo.resize(3);
    _featureInfo[0]._count =  _featureInfo[1]._count =  _featureInfo[2]._count = 0;
}

FeatureCoverage::FeatureCoverage(const Resource& resource) : Coverage(resource),_featureTypes(itUNKNOWN),_featureFactory(0)
{
    _featureInfo.resize(3);
    _featureInfo[0]._count =  _featureInfo[1]._count =  _featureInfo[2]._count = 0;
}

IlwisTypes FeatureCoverage::featureTypes() const
{
    return _featureTypes;
}

void FeatureCoverage::featureTypes(IlwisTypes types)
{
    _featureTypes = types;
}

SPFeatureI FeatureCoverage::newFeature(const Geometry& geom) {
    Locker lock(_mutex);
    SPFeatureI newfeature = createNewFeature(geom.ilwisType());
    if (newfeature != nullptr)
        newfeature->set(geom);
    return newfeature;
}

SPFeatureI FeatureCoverage::newFeatureFrom(const SPFeatureI& existingFeature, const ICoordinateSystem& csySource) {
    Locker lock(_mutex);

    SPFeatureI newfeature = createNewFeature(existingFeature->ilwisType());
    if (newfeature == nullptr)
        return newfeature;

    for(int i=0; i < existingFeature->trackSize(); ++i){
          Geometry geom = existingFeature->geometry().transform(coordinateSystem(), csySource);
          newfeature->set(geom, i);
    }
    return newfeature;
}

SPFeatureI FeatureCoverage::createNewFeature(IlwisTypes tp) {
    if ( isReadOnly())
        return SPFeatureI();
    changed(true);

    _featureTypes |= tp;
    if ( _featureFactory == 0) {
        _featureFactory = kernel()->factory<FeatureFactory>("FeatureFactory","ilwis");
    }
    _record.reset(new AttributeRecord(attributeTable(),FEATUREIDCOLUMN ));

    CreateFeature create = _featureFactory->getCreator("feature");
    IFeatureCoverage fcoverage;
    fcoverage.set(this);
    SPFeatureI newFeature(create(this));

    _record.reset(new AttributeRecord(attributeTable(),FEATUREIDCOLUMN ));
    quint32 colIndex = _record->columnIndex(FEATUREIDCOLUMN);
    if ( colIndex == iUNDEF) {
        ERROR1(ERR_NO_INITIALIZED_1, TR("attribute table"));
        return SPFeatureI();
    }
    _record->cellByRecord(_features.size(), colIndex, newFeature->featureid(), -1);
    _features.push_back(newFeature);
    quint32 cnt = featureCount(tp);
    setFeatureCount(tp,++cnt );
    return _features.back();
}

void FeatureCoverage::setFeatureCount(IlwisTypes types, quint32 cnt)
{
    Locker lock(_mutex2);
     _featureTypes |= types;
    switch(types){
    case itPOINT:
        _featureInfo[0]._count = cnt;break;
    case itLINE:
        _featureInfo[1]._count = cnt; break;
    case itPOLYGON:
        _featureInfo[2]._count = cnt; break;
    }
}

IlwisTypes FeatureCoverage::ilwisType() const
{
    return itFEATURE;
}

FeatureCoverage *FeatureCoverage::copy()
{
    FeatureCoverage *fcov = new FeatureCoverage();
    copyTo(fcov);
    return fcov;
}

QSharedPointer<AttributeRecord> FeatureCoverage::record() const
{
    return _record;
}

void FeatureCoverage::copyTo(IlwisObject *obj)
{
    Coverage::copyTo(obj);
    FeatureCoverage *fcov = static_cast<FeatureCoverage *>(obj);
    fcov->_featureTypes = _featureTypes;
    fcov->_featureInfo = _featureInfo;
    fcov->_features = _features;
}

quint32 FeatureCoverage::featureCount(IlwisTypes types, int ) const
{
    switch(types){
    case itPOINT:
        return _featureInfo[0]._count;break;
    case itLINE:
        return _featureInfo[1]._count; break;
    case itPOLYGON:
        return _featureInfo[2]._count; break;
    default:
        return _featureInfo[0]._count + _featureInfo[1]._count + _featureInfo[2]._count;

    }
    return 0;
}

//-----------------------------------------------------------------

<|endoftext|>


<commit_before>#include <pthread.h>
#include <iostream.h>
#include "Instrument.h"
#include "rt.h"
#include "rtdefs.h"
#include "../Minc/notetags.h"
#ifdef USE_SNDLIB
#include "../sndlib/sndlib.h"
#endif

#ifdef DEBUG
#include <stdio.h>
#endif

extern int setinput(float, Instrument*);
extern InputDesc inputFileTable[];
extern int rtInteractive;
extern pthread_mutex_t pfieldLock;

Instrument::Instrument()
{
  int i;

  fileOffset = 0;
  fdIndex = -1;
  sfile_on = 0; // default is no input soundfile
  start = 0.0;
  dur = 0.0;
  cursamp = 0;
  endsamp = 0;
  chunkstart = 0;
  chunksamps = 0;

  if (tags_on) {
    pthread_mutex_lock(&pfieldLock);
    for (i = 0; i < MAXPUPS; i++) // initialize this element
      pupdatevals[curtag][i] = NOPUPDATE;
    mytag = curtag++;
    if (curtag >= MAXPUPARR) curtag = 1; // wrap it around
    // 0 is reserved for all-note rtupdates
    pthread_mutex_unlock(&pfieldLock);
  }
}

Instrument::~Instrument()
{
	if (sfile_on)
		gone(); // decrement input soundfile reference
}

int Instrument::init(float p[], short n_args)
{
	cout << "you haven't defined an init member of your Instrument class!" << endl;
	return -1;
}

int Instrument::run()
{
	cout << "you haven't defined a run member of your Instrument class!" << endl;
	return -1;
}

float Instrument::getstart()
{
	return start;
}

float Instrument::getdur()
{
	return dur;
}

int Instrument::getendsamp()
{
	return endsamp;
}

void Instrument::setchunk(int csamps)
{
  chunksamps = csamps;
}

void Instrument::setchunkstart(int csamps)
{
	chunkstart = csamps;
}

void Instrument::setendsamp(int end)
{
	endsamp = end;
}

void Instrument::gone()
{
  // If the reference count on the file referenced by the instrument
  // reaches zero, close the input soundfile and set the state to
  // make sure this is obvious

#ifdef DEBUG
  printf("Instrument::gone(this=0x%x): index %d refcount = %d\n",
	 this, fdIndex, inputFileTable[fdIndex].refcount);
#endif

  // BGG -- added this to prevent file closings in interactive mode
  // we don't know if a file will be referenced again in the future
  if (!rtInteractive) {
    if (fdIndex >= 0 && --inputFileTable[fdIndex].refcount <= 0) {
      if (inputFileTable[fdIndex].fd > 0) {
#ifdef DEBUG
	printf("\tclosing fd %d\n", inputFileTable[fdIndex].fd);
#endif

#ifdef USE_SNDLIB
	clm_close(inputFileTable[fdIndex].fd);
#else /* !USE_SNDLIB */
  #ifdef sgi
	// free the file handle opened for this file
	afCloseFile((AFfilehandle) inputFileTable[fdIndex].handle);
  #else
	close(inputFileTable[fdIndex].fd);
  #endif
#endif /* !USE_SNDLIB */
      }
      inputFileTable[fdIndex].fd = 0;
#ifdef USE_SNDLIB
      inputFileTable[fdIndex].header_type = unsupported_sound_file;
      inputFileTable[fdIndex].data_format = snd_unsupported;
#else /* !USE_SNDLIB */
  #ifdef sgi
      inputFileTable[fdIndex].handle = NULL;
  #endif
#endif /* !USE_SNDLIB */
      inputFileTable[fdIndex].data_location = 0;
      inputFileTable[fdIndex].dur = 0.0;
      inputFileTable[fdIndex].filename[0] = '\0';
      fdIndex = -1;
    }
  }
}

<commit_msg>Add copyright notice. Move some globals to globals.h.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <globals.h>
#include <pthread.h>
#include <iostream.h>
#include "Instrument.h"
#include "rt.h"
#include "rtdefs.h"
#include "../Minc/notetags.h"
#ifdef USE_SNDLIB
#include "../sndlib/sndlib.h"
#endif

#ifdef DEBUG
#include <stdio.h>
#endif

extern int setinput(float, Instrument*);
extern InputDesc inputFileTable[];

Instrument::Instrument()
{
  int i;

  fileOffset = 0;
  fdIndex = -1;
  sfile_on = 0; // default is no input soundfile
  start = 0.0;
  dur = 0.0;
  cursamp = 0;
  endsamp = 0;
  chunkstart = 0;
  chunksamps = 0;

  if (tags_on) {
    pthread_mutex_lock(&pfieldLock);
    for (i = 0; i < MAXPUPS; i++) // initialize this element
      pupdatevals[curtag][i] = NOPUPDATE;
    mytag = curtag++;
    if (curtag >= MAXPUPARR) curtag = 1; // wrap it around
    // 0 is reserved for all-note rtupdates
    pthread_mutex_unlock(&pfieldLock);
  }
}

Instrument::~Instrument()
{
	if (sfile_on)
		gone(); // decrement input soundfile reference
}

int Instrument::init(float p[], short n_args)
{
	cout << "you haven't defined an init member of your Instrument class!" << endl;
	return -1;
}

int Instrument::run()
{
	cout << "you haven't defined a run member of your Instrument class!" << endl;
	return -1;
}

float Instrument::getstart()
{
	return start;
}

float Instrument::getdur()
{
	return dur;
}

int Instrument::getendsamp()
{
	return endsamp;
}

void Instrument::setchunk(int csamps)
{
  chunksamps = csamps;
}

void Instrument::setchunkstart(int csamps)
{
	chunkstart = csamps;
}

void Instrument::setendsamp(int end)
{
	endsamp = end;
}

void Instrument::gone()
{
  // If the reference count on the file referenced by the instrument
  // reaches zero, close the input soundfile and set the state to
  // make sure this is obvious

#ifdef DEBUG
  printf("Instrument::gone(this=0x%x): index %d refcount = %d\n",
	 this, fdIndex, inputFileTable[fdIndex].refcount);
#endif

  // BGG -- added this to prevent file closings in interactive mode
  // we don't know if a file will be referenced again in the future
  if (!rtInteractive) {
    if (fdIndex >= 0 && --inputFileTable[fdIndex].refcount <= 0) {
      if (inputFileTable[fdIndex].fd > 0) {
#ifdef DEBUG
	printf("\tclosing fd %d\n", inputFileTable[fdIndex].fd);
#endif

#ifdef USE_SNDLIB
	clm_close(inputFileTable[fdIndex].fd);
#else /* !USE_SNDLIB */
  #ifdef sgi
	// free the file handle opened for this file
	afCloseFile((AFfilehandle) inputFileTable[fdIndex].handle);
  #else
	close(inputFileTable[fdIndex].fd);
  #endif
#endif /* !USE_SNDLIB */
      }
      inputFileTable[fdIndex].fd = 0;
#ifdef USE_SNDLIB
      inputFileTable[fdIndex].header_type = unsupported_sound_file;
      inputFileTable[fdIndex].data_format = snd_unsupported;
#else /* !USE_SNDLIB */
  #ifdef sgi
      inputFileTable[fdIndex].handle = NULL;
  #endif
#endif /* !USE_SNDLIB */
      inputFileTable[fdIndex].data_location = 0;
      inputFileTable[fdIndex].dur = 0.0;
      inputFileTable[fdIndex].filename[0] = '\0';
      fdIndex = -1;
    }
  }
}

<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
/* Functions for creating and modifying control streams.  These can be
   passed from a script to RTcmix functions that accept them.  See also
   table.cpp for a similar set of functions.

   John Gibson, 8/14/04
*/
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

#include <rtcmix_types.h>
#include <PField.h>
#include <ugens.h>		// for warn, die

#if !defined(SHAREDLIBDIR) || !defined(SHLIB_SUFFIX)
#error "Compile flags are missing macros for SHAREDLIBDIR and/or SHLIB_SUFFIX"
#endif

// --------------------------------------------------------- local utilities ---
void *
find_dso(const char *selector)
{
	char loadPath[1024];
	dlerror();	// clear error queue
	sprintf(loadPath, "%s/lib%sconn.%s", SHAREDLIBDIR, selector, SHLIB_SUFFIX);
	void *dso = dlopen(loadPath, RTLD_LAZY);
	if (!dso) {
		die("makeconnection", "dynamic load failed: %s\n", dlerror());
	}
	return dso;
}

// =============================================================================
// The remaining functions are public, callable from scripts.

extern "C" {
	Handle makeconnection(const Arg args[], const int nargs);
};

typedef Handle (*HandleCreator)(const Arg[], const int);

// ---------------------------------------------------------- makeconnection ---
Handle
makeconnection(const Arg args[], const int nargs)
{
	if (!args[0].isType(StringType)) {
		die("makeconnection", "First argument must be a string giving "
			"connection type, e.g. \"mouseX\", \"midi\".");
		return NULL;
	}

	const char *selector = (const char *) args[0];
	if (args[0] == "mouseX" || args[0] == "mouseY")
		selector = "mouse";

	Handle handle = NULL;
	HandleCreator creator = NULL;

	void *dso = find_dso(selector);
	if (dso) {
		creator = (HandleCreator) dlsym(dso, "create_handle");
		if (creator) {
			handle = (*creator)(args, nargs);
		}
		else {
			die("makeconnection", "symbol lookup failed: %s\n", dlerror());
		}
	}
	return handle;
}

<commit_msg>makeconnection() strips arg[0] (selector) off list before handing to DSO function.<commit_after>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
/* Functions for creating and modifying control streams.  These can be
   passed from a script to RTcmix functions that accept them.  See also
   table.cpp for a similar set of functions.

   John Gibson, 8/14/04
*/
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

#include <rtcmix_types.h>
#include <PField.h>
#include <ugens.h>		// for warn, die

#if !defined(SHAREDLIBDIR) || !defined(SHLIB_SUFFIX)
#error "Compile flags are missing macros for SHAREDLIBDIR and/or SHLIB_SUFFIX"
#endif

// --------------------------------------------------------- local utilities ---
void *
find_dso(const char *selector)
{
	char loadPath[1024];
	dlerror();	// clear error queue
	sprintf(loadPath, "%s/lib%sconn.%s", SHAREDLIBDIR, selector, SHLIB_SUFFIX);
	void *dso = dlopen(loadPath, RTLD_LAZY);
	if (!dso) {
		die("makeconnection", "dynamic load failed: %s\n", dlerror());
	}
	return dso;
}

// =============================================================================
// The remaining functions are public, callable from scripts.

extern "C" {
	Handle makeconnection(const Arg args[], const int nargs);
};

typedef Handle (*HandleCreator)(const Arg[], const int);

// ---------------------------------------------------------- makeconnection ---
Handle
makeconnection(const Arg args[], const int nargs)
{
	if (!args[0].isType(StringType)) {
		die("makeconnection", "First argument must be a string giving "
			"connection type, e.g. \"mouse\", \"midi\".");
		return NULL;
	}

	if (args[0] == "mouseX" || args[0] == "mouseY") {
		die("makeconnection",
			"New calling convention for mouse is (\"mouse\", \"X\", ...)");
		return NULL;
	}

	Handle handle = NULL;
	HandleCreator creator = NULL;
	const char *selector = (const char *) args[0];

	void *dso = find_dso(selector);
	if (dso) {
		creator = (HandleCreator) dlsym(dso, "create_handle");
		if (creator) {
			// Pass 2nd thru last args, leaving off selector
			handle = (*creator)(&args[1], nargs - 1);
		}
		else {
			die("makeconnection", "symbol lookup failed: %s\n", dlerror());
		}
	}
	return handle;
}

<|endoftext|>