initial drop
This commit is contained in:
commit
e9b8aa88c0
33
main.cpp
Normal file
33
main.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
|
||||||
|
using namespace metacall;
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
Client client;
|
||||||
|
return 0;
|
||||||
|
}
|
134
mc_binding-inl.hpp
Normal file
134
mc_binding-inl.hpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Binding
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)()) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor0p<R>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor1p<R, P1>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor2p<R, P1, P2>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor3p<R, P1, P2, P3>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor4p<R, P1, P2, P3, P4>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor5p<R, P1, P2, P3, P4, P5>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor6p<R, P1, P2, P3, P4, P5, P6>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor7p<R, P1, P2, P3, P4, P5, P6, P7>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor8p<R, P1, P2, P3, P4, P5, P6, P7, P8>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||||
|
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8, P9)) {
|
||||||
|
if (functors_.find(token) == functors_.end()) {
|
||||||
|
functors_[token] = new Functor9p<R, P1, P2, P3, P4, P5, P6, P7, P8, P9>(function);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
69
mc_binding.cpp
Normal file
69
mc_binding.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Binding
|
||||||
|
//
|
||||||
|
|
||||||
|
Binding::~Binding() {
|
||||||
|
unbindAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding::CallResult Binding::call(const Token& token, Deserializer* args, Serializer* ret) const {
|
||||||
|
const FunctorMap::const_iterator iter = functors_.find(token);
|
||||||
|
|
||||||
|
if (iter == functors_.end()) {
|
||||||
|
return CALL_RESULT_UNBOUND_FUNC;
|
||||||
|
}
|
||||||
|
if (!iter->second->call(args, ret)) {
|
||||||
|
return CALL_RESULT_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CALL_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Binding::unbind(const Token& token) {
|
||||||
|
FunctorMap::iterator iter = functors_.find(token);
|
||||||
|
if (iter != functors_.end()) {
|
||||||
|
delete iter->second;
|
||||||
|
functors_.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Binding::unbindAll() {
|
||||||
|
for (FunctorMap::iterator iter = functors_.begin(); iter != functors_.end(); ++iter) {
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
functors_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
76
mc_binding.hpp
Normal file
76
mc_binding.hpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Binding
|
||||||
|
//
|
||||||
|
|
||||||
|
class Binding {
|
||||||
|
public:
|
||||||
|
enum CallResult {
|
||||||
|
CALL_RESULT_SUCCESS,
|
||||||
|
CALL_RESULT_INVALID_ARGS,
|
||||||
|
CALL_RESULT_UNBOUND_FUNC
|
||||||
|
};
|
||||||
|
|
||||||
|
~Binding();
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
bool bind (const Token& token, R(*function)());
|
||||||
|
template <typename R, typename P1>
|
||||||
|
bool bind (const Token& token, R(*function)(P1));
|
||||||
|
template <typename R, typename P1, typename P2>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3, P4));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8));
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||||
|
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8, P9));
|
||||||
|
|
||||||
|
CallResult call (const Token& token, Deserializer* args, Serializer* ret) const;
|
||||||
|
void unbind (const Token& token);
|
||||||
|
void unbindAll ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<unsigned, IFunctor*> FunctorMap;
|
||||||
|
FunctorMap functors_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
102
mc_buffer.cpp
Normal file
102
mc_buffer.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_buffer.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
Buffer::Buffer(const void* data, int count) {
|
||||||
|
setData(data, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Buffer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::addToBack(const void* data, int bytes) {
|
||||||
|
data_.insert(
|
||||||
|
data_.end(),
|
||||||
|
static_cast<const byte*>(data),
|
||||||
|
static_cast<const byte*>(data) + bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::addToFront(const void* data, int bytes) {
|
||||||
|
data_.insert(
|
||||||
|
data_.begin(),
|
||||||
|
static_cast<const byte*>(data),
|
||||||
|
static_cast<const byte*>(data) + bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buffer::removeFromFront(void* data, int bytes) {
|
||||||
|
bytes = std::min(static_cast<size_t>(bytes), data_.size());
|
||||||
|
if (data != NULL) {
|
||||||
|
memcpy(data, &data_[0], bytes);
|
||||||
|
}
|
||||||
|
data_.erase(data_.begin(), data_.begin() + bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buffer::removeFromBack(void* data, int bytes) {
|
||||||
|
bytes = std::min(static_cast<size_t>(bytes), data_.size());
|
||||||
|
if (data != NULL) {
|
||||||
|
memcpy(data, &data_[data_.size() - bytes], bytes);
|
||||||
|
}
|
||||||
|
data_.erase(data_.end() - bytes, data_.end());
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::clear() {
|
||||||
|
data_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::setData(const void* data, int bytes) {
|
||||||
|
data_.assign(
|
||||||
|
static_cast<const byte*>(data),
|
||||||
|
static_cast<const byte*>(data) + bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* Buffer::data() const {
|
||||||
|
return &data_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Buffer::data() {
|
||||||
|
return &data_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buffer::bytes() const {
|
||||||
|
return data_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
56
mc_buffer.hpp
Normal file
56
mc_buffer.hpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
class Buffer {
|
||||||
|
public:
|
||||||
|
Buffer(const void* data, int bytes);
|
||||||
|
Buffer();
|
||||||
|
|
||||||
|
void addToBack (const void* data, int bytes);
|
||||||
|
void addToFront (const void* data, int bytes);
|
||||||
|
int removeFromFront (void* data, int bytes);
|
||||||
|
int removeFromBack (void* data, int bytes);
|
||||||
|
void clear ();
|
||||||
|
|
||||||
|
void setData (const void* data, int bytes);
|
||||||
|
const void* data () const;
|
||||||
|
void* data ();
|
||||||
|
int bytes () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<byte> data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
97
mc_client.cpp
Normal file
97
mc_client.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_client.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Client
|
||||||
|
//
|
||||||
|
|
||||||
|
Client::Client() :
|
||||||
|
stream_(&socket_),
|
||||||
|
protocol_(&stream_, &binding_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::advance() {
|
||||||
|
if (!socket_.opened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket_.connected()) {
|
||||||
|
protocol_.advance();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::connect(const char name[], int port) {
|
||||||
|
disconnect();
|
||||||
|
|
||||||
|
socket_.open();
|
||||||
|
socket_.setNagle(false);
|
||||||
|
|
||||||
|
if (!socket_.connect(name, port)) {
|
||||||
|
disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_.setBlocking(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::disconnect() {
|
||||||
|
protocol_.clearHandlers();
|
||||||
|
stream_.reset();
|
||||||
|
socket_.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::connected() const {
|
||||||
|
return socket_.connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Protocol* Client::protocol() const {
|
||||||
|
return &protocol_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Protocol* Client::protocol() {
|
||||||
|
return &protocol_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Binding* Client::binding() const {
|
||||||
|
return &binding_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding* Client::binding() {
|
||||||
|
return &binding_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
58
mc_client.hpp
Normal file
58
mc_client.hpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Client
|
||||||
|
//
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
Client();
|
||||||
|
|
||||||
|
void advance ();
|
||||||
|
|
||||||
|
bool connect (const char name[], int port);
|
||||||
|
void disconnect ();
|
||||||
|
bool connected () const;
|
||||||
|
|
||||||
|
const Protocol* protocol () const;
|
||||||
|
Protocol* protocol ();
|
||||||
|
const Binding* binding () const;
|
||||||
|
Binding* binding ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Socket socket_;
|
||||||
|
Stream stream_;
|
||||||
|
Binding binding_;
|
||||||
|
Protocol protocol_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
56
mc_common.hpp
Normal file
56
mc_common.hpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Macros
|
||||||
|
//
|
||||||
|
|
||||||
|
#define IS_TRUE(x) ((x) != 0)
|
||||||
|
#define ASSERT assert
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Types
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef unsigned __int8 byte;
|
||||||
|
typedef unsigned __int16 word;
|
||||||
|
typedef unsigned __int32 dword;
|
||||||
|
typedef unsigned __int64 qword;
|
||||||
|
#else
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short word;
|
||||||
|
typedef unsigned int dword;
|
||||||
|
typedef unsigned long int qword;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
755
mc_functor.hpp
Normal file
755
mc_functor.hpp
Normal file
@ -0,0 +1,755 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// IFunctor
|
||||||
|
//
|
||||||
|
|
||||||
|
class IFunctor {
|
||||||
|
public:
|
||||||
|
virtual bool call(Deserializer* args, Serializer* ret) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor0p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class Functor0p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R(*F)();
|
||||||
|
|
||||||
|
Functor0p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer*, Serializer* ret) const {
|
||||||
|
ret->write(function_());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Functor0p<void> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void(*F)();
|
||||||
|
|
||||||
|
Functor0p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer*, Serializer*) const {
|
||||||
|
function_();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor1p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1>
|
||||||
|
class Functor1p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1);
|
||||||
|
|
||||||
|
Functor1p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
|
||||||
|
const bool success = args->read(&p1);
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1>
|
||||||
|
class Functor1p<void, P1> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1);
|
||||||
|
|
||||||
|
Functor1p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
|
||||||
|
const bool success = args->read(&p1);
|
||||||
|
if (success) {
|
||||||
|
function_(p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor2p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2>
|
||||||
|
class Functor2p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2);
|
||||||
|
|
||||||
|
Functor2p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2>
|
||||||
|
class Functor2p<void, P1, P2> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2);
|
||||||
|
|
||||||
|
Functor2p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor3p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3>
|
||||||
|
class Functor3p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3);
|
||||||
|
|
||||||
|
Functor3p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3>
|
||||||
|
class Functor3p<void, P1, P2, P3> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3);
|
||||||
|
|
||||||
|
Functor3p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor4p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4>
|
||||||
|
class Functor4p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3, P4);
|
||||||
|
|
||||||
|
Functor4p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3, p4));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4>
|
||||||
|
class Functor4p<void, P1, P2, P3, P4> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3, P4);
|
||||||
|
|
||||||
|
Functor4p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3, p4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor5p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||||
|
class Functor5p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3, P4, P5);
|
||||||
|
|
||||||
|
Functor5p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3, p4, p5));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||||
|
class Functor5p<void, P1, P2, P3, P4, P5> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3, P4, P5);
|
||||||
|
|
||||||
|
Functor5p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3, p4, p5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor6p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||||
|
class Functor6p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3, P4, P5, P6);
|
||||||
|
|
||||||
|
Functor6p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3, p4, p5, p6));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||||
|
class Functor6p<void, P1, P2, P3, P4, P5, P6> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3, P4, P5, P6);
|
||||||
|
|
||||||
|
Functor6p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3, p4, p5, p6);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor7p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||||
|
class Functor7p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7);
|
||||||
|
|
||||||
|
Functor7p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
typename StripConstRef<P7>::Type p7;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6) &&
|
||||||
|
args->read(&p7);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3, p4, p5, p6, p7));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||||
|
class Functor7p<void, P1, P2, P3, P4, P5, P6, P7> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3, P4, P5, P6, P7);
|
||||||
|
|
||||||
|
Functor7p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
typename StripConstRef<P7>::Type p7;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6) &&
|
||||||
|
args->read(&p7);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3, p4, p5, p6, p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor8p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||||
|
class Functor8p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7, P8);
|
||||||
|
|
||||||
|
Functor8p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
typename StripConstRef<P7>::Type p7;
|
||||||
|
typename StripConstRef<P8>::Type p8;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6) &&
|
||||||
|
args->read(&p7) &&
|
||||||
|
args->read(&p8);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3, p4, p5, p6, p7, p8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||||
|
class Functor8p<void, P1, P2, P3, P4, P5, P6, P7, P8> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3, P4, P5, P6, P7, P8);
|
||||||
|
|
||||||
|
Functor8p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
typename StripConstRef<P7>::Type p7;
|
||||||
|
typename StripConstRef<P8>::Type p8;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6) &&
|
||||||
|
args->read(&p7) &&
|
||||||
|
args->read(&p8);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3, p4, p5, p6, p7, p8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functor9p
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||||
|
class Functor9p : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
|
||||||
|
|
||||||
|
Functor9p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer* ret) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
typename StripConstRef<P7>::Type p7;
|
||||||
|
typename StripConstRef<P8>::Type p8;
|
||||||
|
typename StripConstRef<P9>::Type p9;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6) &&
|
||||||
|
args->read(&p7) &&
|
||||||
|
args->read(&p8) &&
|
||||||
|
args->read(&p9);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ret->write(function_(p1, p2, p3, p4, p5, p6, p7, p8, p9));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||||
|
class Functor9p<void, P1, P2, P3, P4, P5, P6, P7, P8, P9> : public IFunctor {
|
||||||
|
public:
|
||||||
|
typedef void (*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
|
||||||
|
|
||||||
|
Functor9p(F function) :
|
||||||
|
function_(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool call(Deserializer* args, Serializer*) const {
|
||||||
|
typename StripConstRef<P1>::Type p1;
|
||||||
|
typename StripConstRef<P2>::Type p2;
|
||||||
|
typename StripConstRef<P3>::Type p3;
|
||||||
|
typename StripConstRef<P4>::Type p4;
|
||||||
|
typename StripConstRef<P5>::Type p5;
|
||||||
|
typename StripConstRef<P6>::Type p6;
|
||||||
|
typename StripConstRef<P7>::Type p7;
|
||||||
|
typename StripConstRef<P8>::Type p8;
|
||||||
|
typename StripConstRef<P9>::Type p9;
|
||||||
|
|
||||||
|
const bool success =
|
||||||
|
args->read(&p1) &&
|
||||||
|
args->read(&p2) &&
|
||||||
|
args->read(&p3) &&
|
||||||
|
args->read(&p4) &&
|
||||||
|
args->read(&p5) &&
|
||||||
|
args->read(&p6) &&
|
||||||
|
args->read(&p7) &&
|
||||||
|
args->read(&p8) &&
|
||||||
|
args->read(&p9);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
function_(p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
88
mc_meta.hpp
Normal file
88
mc_meta.hpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Meta
|
||||||
|
//
|
||||||
|
|
||||||
|
qword serialize (class Serializer*, ...);
|
||||||
|
qword deserialize (class Deserializer*, ...);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsSerializable {
|
||||||
|
enum {
|
||||||
|
Value = sizeof(bool) == sizeof(
|
||||||
|
serialize(
|
||||||
|
static_cast<Serializer*>(0),
|
||||||
|
*static_cast<T*>(0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsDeserializable {
|
||||||
|
enum {
|
||||||
|
Value = sizeof(bool) == sizeof(
|
||||||
|
deserialize(
|
||||||
|
static_cast<Deserializer*>(0),
|
||||||
|
static_cast<T*>(0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct StripRef {
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct StripRef<T&> {
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct StripConst {
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct StripConst<const T> {
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct StripConstRef {
|
||||||
|
typedef typename StripConst<typename StripRef<T>::Type >::Type Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
112
mc_packet.hpp
Normal file
112
mc_packet.hpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constants
|
||||||
|
//
|
||||||
|
|
||||||
|
enum PacketConst {
|
||||||
|
PACKET_CONST_MAGIC = 0x55534544,
|
||||||
|
PACKET_CONST_VERSION = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PacketId {
|
||||||
|
PACKET_ID_INVALID,
|
||||||
|
PACKET_ID_FUNCTION_CALL_REQUEST,
|
||||||
|
PACKET_ID_FUNCTION_CALL_REPLY
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PacketHeader
|
||||||
|
//
|
||||||
|
|
||||||
|
struct PacketHeader {
|
||||||
|
PacketHeader() :
|
||||||
|
magic(0),
|
||||||
|
id(PACKET_ID_INVALID),
|
||||||
|
size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
dword magic;
|
||||||
|
byte id;
|
||||||
|
dword size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PacketInvokeRequest
|
||||||
|
//
|
||||||
|
|
||||||
|
struct PacketInvokeRequest {
|
||||||
|
PacketInvokeRequest() :
|
||||||
|
function(0),
|
||||||
|
taskId(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Id = PACKET_ID_FUNCTION_CALL_REQUEST
|
||||||
|
};
|
||||||
|
|
||||||
|
dword function;
|
||||||
|
dword taskId;
|
||||||
|
Buffer data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PacketInvokeReply
|
||||||
|
//
|
||||||
|
|
||||||
|
struct PacketInvokeReply {
|
||||||
|
PacketInvokeReply() :
|
||||||
|
flags(0),
|
||||||
|
taskId(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Id = PACKET_ID_FUNCTION_CALL_REPLY
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FLAG_UNBOUND_FUNC = 1 << 0,
|
||||||
|
FLAG_INVALID_ARGS = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
word flags;
|
||||||
|
dword taskId;
|
||||||
|
Buffer data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
174
mc_protocol-inl.hpp
Normal file
174
mc_protocol-inl.hpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
template <typename P1>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
serializer.write(p1);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3 & p3, const P4& p4) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
serializer.write(p4);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
serializer.write(p4);
|
||||||
|
serializer.write(p5);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
serializer.write(p4);
|
||||||
|
serializer.write(p5);
|
||||||
|
serializer.write(p6);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
serializer.write(p4);
|
||||||
|
serializer.write(p5);
|
||||||
|
serializer.write(p6);
|
||||||
|
serializer.write(p7);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
serializer.write(p4);
|
||||||
|
serializer.write(p5);
|
||||||
|
serializer.write(p6);
|
||||||
|
serializer.write(p7);
|
||||||
|
serializer.write(p8);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||||
|
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8, const P9& p9) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Serializer serializer(&packetRequest.data);
|
||||||
|
|
||||||
|
serializer.write(p1);
|
||||||
|
serializer.write(p2);
|
||||||
|
serializer.write(p3);
|
||||||
|
serializer.write(p4);
|
||||||
|
serializer.write(p5);
|
||||||
|
serializer.write(p6);
|
||||||
|
serializer.write(p7);
|
||||||
|
serializer.write(p8);
|
||||||
|
serializer.write(p9);
|
||||||
|
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
TaskState Protocol::queryResult(TaskId id, R* result) {
|
||||||
|
TaskMap::const_iterator iter = taskMap_.find(id);
|
||||||
|
if (iter == taskMap_.end()) {
|
||||||
|
return TASK_STATE_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskEntry& entry = iter->second;
|
||||||
|
if (entry.state == TASK_STATE_READY) {
|
||||||
|
Deserializer deserializer(&entry.data);
|
||||||
|
if (!deserializer.read(result)) {
|
||||||
|
entry.state = TASK_STATE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
208
mc_protocol.cpp
Normal file
208
mc_protocol.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_protocol.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Protocol
|
||||||
|
//
|
||||||
|
|
||||||
|
Protocol::Protocol(Stream* stream, Binding* binding) :
|
||||||
|
stream_(stream),
|
||||||
|
binding_(binding),
|
||||||
|
rate_(64)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Protocol::advance() {
|
||||||
|
if (!stream_->socket()->connected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < rate_; ++i) {
|
||||||
|
if (advanceStream() != Stream::STATE_READY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TaskMap::iterator> processed;
|
||||||
|
for (TaskMap::iterator iter = taskMap_.begin(); iter != taskMap_.end(); ++iter) {
|
||||||
|
TaskEntry& entry = iter->second;
|
||||||
|
switch (entry.state) {
|
||||||
|
case TASK_STATE_READY:
|
||||||
|
case TASK_STATE_ERROR:
|
||||||
|
processed.push_back(iter);
|
||||||
|
for (size_t i = 0; i < entry.handlers.size(); ++i) {
|
||||||
|
HandlerEntry& handler = entry.handlers[i];
|
||||||
|
handler.handler(this, iter->first, entry.state, handler.userPtr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < processed.size(); ++i) {
|
||||||
|
taskMap_.erase(processed[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Protocol::setRate(int rate) {
|
||||||
|
rate_ = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Protocol::setHandler(TaskId id, HandlerProc handler, void* userPtr) {
|
||||||
|
const TaskMap::iterator iter = taskMap_.find(id);
|
||||||
|
if (iter == taskMap_.end() || iter->second.state != TASK_STATE_PENDING) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->second.handlers.push_back(HandlerEntry(handler, userPtr));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Protocol::clearHandler(TaskId id) {
|
||||||
|
const TaskMap::iterator iter = taskMap_.find(id);
|
||||||
|
if (iter != taskMap_.end()) {
|
||||||
|
taskMap_.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Protocol::clearHandlers() {
|
||||||
|
for (TaskMap::iterator iter = taskMap_.begin(); iter != taskMap_.end(); ++iter) {
|
||||||
|
iter->second.handlers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskState Protocol::queryState(TaskId id) const {
|
||||||
|
const TaskMap::const_iterator iter = taskMap_.find(id);
|
||||||
|
return iter == taskMap_.end() ? TASK_STATE_UNDEFINED : iter->second.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::State Protocol::advanceStream() {
|
||||||
|
stream_->advance();
|
||||||
|
|
||||||
|
PacketHeader header;
|
||||||
|
int headerSize = 0;
|
||||||
|
|
||||||
|
Stream::State state = stream_->peek(&header, &headerSize);
|
||||||
|
if (state == Stream::STATE_READY) {
|
||||||
|
switch (header.id) {
|
||||||
|
case PACKET_ID_FUNCTION_CALL_REQUEST:
|
||||||
|
state = advanceInvokeRequest();
|
||||||
|
break;
|
||||||
|
case PACKET_ID_FUNCTION_CALL_REPLY:
|
||||||
|
state = advanceInvokeReply();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
state = Stream::STATE_ERROR_PROTOCOL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::State Protocol::advanceInvokeReply() {
|
||||||
|
PacketInvokeReply packetReply;
|
||||||
|
Deserializer deserializer(&packetReply.data);
|
||||||
|
|
||||||
|
Stream::State state = stream_->receive(&packetReply);
|
||||||
|
if (state == Stream::STATE_READY) {
|
||||||
|
const TaskMap::iterator iter = taskMap_.find(static_cast<TaskId>(packetReply.taskId));
|
||||||
|
if (iter == taskMap_.end()) {
|
||||||
|
state = Stream::STATE_ERROR_PROTOCOL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const bool error =
|
||||||
|
IS_TRUE(packetReply.flags & PacketInvokeReply::FLAG_UNBOUND_FUNC) ||
|
||||||
|
IS_TRUE(packetReply.flags & PacketInvokeReply::FLAG_INVALID_ARGS);
|
||||||
|
|
||||||
|
iter->second.state = error ? TASK_STATE_ERROR : TASK_STATE_READY;
|
||||||
|
iter->second.data = packetReply.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::State Protocol::advanceInvokeRequest() {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
Deserializer deserializer(&packetRequest.data);
|
||||||
|
|
||||||
|
const Stream::State state = stream_->receive(&packetRequest);
|
||||||
|
if (state == Stream::STATE_READY) {
|
||||||
|
PacketInvokeReply packetReply;
|
||||||
|
packetReply.taskId = packetRequest.taskId;
|
||||||
|
|
||||||
|
Serializer serializer(&packetReply.data);
|
||||||
|
switch (binding_->call(packetRequest.function, &deserializer, &serializer)) {
|
||||||
|
case Binding::CALL_RESULT_INVALID_ARGS:
|
||||||
|
packetReply.flags |= PacketInvokeReply::FLAG_INVALID_ARGS;
|
||||||
|
break;
|
||||||
|
case Binding::CALL_RESULT_UNBOUND_FUNC:
|
||||||
|
packetReply.flags |= PacketInvokeReply::FLAG_UNBOUND_FUNC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_->send(packetReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskId Protocol::invoke(const Token& token) {
|
||||||
|
PacketInvokeRequest packetRequest;
|
||||||
|
return invokeExec(token, &packetRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskId Protocol::invokeExec(const Token& token, PacketInvokeRequest* packetRequest) {
|
||||||
|
const TaskId taskId = registerTaskId();
|
||||||
|
|
||||||
|
packetRequest->function = token;
|
||||||
|
packetRequest->taskId = taskId;
|
||||||
|
|
||||||
|
if (stream_->send(*packetRequest) != Stream::STATE_READY) {
|
||||||
|
return TASK_ID_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskMap_[taskId] = TaskEntry();
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskId Protocol::registerTaskId() {
|
||||||
|
static int id = TASK_ID_INVALID;
|
||||||
|
while (++id == TASK_ID_INVALID);
|
||||||
|
return static_cast<TaskId>(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
132
mc_protocol.hpp
Normal file
132
mc_protocol.hpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Types
|
||||||
|
//
|
||||||
|
|
||||||
|
enum TaskId {
|
||||||
|
TASK_ID_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TaskState {
|
||||||
|
TASK_STATE_UNDEFINED,
|
||||||
|
TASK_STATE_PENDING,
|
||||||
|
TASK_STATE_READY,
|
||||||
|
TASK_STATE_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*HandlerProc)(
|
||||||
|
class Protocol* protocol,
|
||||||
|
TaskId id,
|
||||||
|
TaskState state,
|
||||||
|
void* userPtr
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Protocol
|
||||||
|
//
|
||||||
|
|
||||||
|
class Protocol {
|
||||||
|
public:
|
||||||
|
Protocol(Stream* stream, Binding* binding);
|
||||||
|
|
||||||
|
void advance ();
|
||||||
|
|
||||||
|
void setRate (int rate);
|
||||||
|
bool setHandler (TaskId id, HandlerProc handler, void* userPtr = NULL);
|
||||||
|
void clearHandler (TaskId id);
|
||||||
|
void clearHandlers ();
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
TaskState queryResult (TaskId id, R* result);
|
||||||
|
TaskState queryState (TaskId id) const;
|
||||||
|
|
||||||
|
TaskId invoke (const Token& token);
|
||||||
|
template <typename P1>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0);
|
||||||
|
template <typename P1, typename P2>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1);
|
||||||
|
template <typename P1, typename P2, typename P3>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2);
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3);
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4);
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5);
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5, const P7& p6);
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5, const P7& p6, const P8& p7);
|
||||||
|
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||||
|
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5, const P7& p6, const P8& p7, const P9& p8);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct HandlerEntry {
|
||||||
|
HandlerEntry(HandlerProc handler, void* userPtr) :
|
||||||
|
handler(handler),
|
||||||
|
userPtr(userPtr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HandlerProc handler;
|
||||||
|
void* userPtr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TaskEntry {
|
||||||
|
TaskEntry() :
|
||||||
|
state(TASK_STATE_PENDING)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::vector<HandlerEntry> HandlerList;
|
||||||
|
HandlerList handlers;
|
||||||
|
TaskState state;
|
||||||
|
Buffer data;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream::State advanceStream ();
|
||||||
|
Stream::State advanceInvokeRequest();
|
||||||
|
Stream::State advanceInvokeReply ();
|
||||||
|
|
||||||
|
TaskId invokeExec (const Token& token, PacketInvokeRequest* packetRequest);
|
||||||
|
static TaskId registerTaskId ();
|
||||||
|
|
||||||
|
typedef std::map<TaskId, TaskEntry> TaskMap;
|
||||||
|
TaskMap taskMap_;
|
||||||
|
Stream* stream_;
|
||||||
|
Binding* binding_;
|
||||||
|
int rate_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
117
mc_serial-inl.hpp
Normal file
117
mc_serial-inl.hpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// TypeReader
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T, bool G>
|
||||||
|
struct TypeReader {
|
||||||
|
static bool read(Deserializer* deserializer, T* data) {
|
||||||
|
return deserialize(deserializer, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct TypeReader<T, false> {
|
||||||
|
static bool read(Deserializer* deserializer, T* data) {
|
||||||
|
const T* const temp = reinterpret_cast<const T*>(deserializer->readRaw(sizeof(T)));
|
||||||
|
if (temp != NULL) {
|
||||||
|
*data = *temp;
|
||||||
|
}
|
||||||
|
return temp != NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool Deserializer::read(T* data) {
|
||||||
|
return TypeReader<T, IsDeserializable<T>::Value>::read(this, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// TypeWriter
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T, bool G>
|
||||||
|
struct TypeWriter {
|
||||||
|
static bool write(Serializer* serializer, const T& data) {
|
||||||
|
return serialize(serializer, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct TypeWriter<T, false> {
|
||||||
|
static bool write(Serializer* serializer, const T& data) {
|
||||||
|
return serializer->writeRaw(&data, sizeof(T));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool Serializer::write(const T& data) {
|
||||||
|
return TypeWriter<T, IsSerializable<T>::Value>::write(this, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Serializers
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool serialize(Serializer* serializer, const ArrayWriter<T>& writer) {
|
||||||
|
serializer->write(writer.count);
|
||||||
|
|
||||||
|
for (int i = 0; i < writer.count; ++i) {
|
||||||
|
serializer->write(writer.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool deserialize(Deserializer* deserializer, ArrayReader<T>* reader) {
|
||||||
|
reader->clear();
|
||||||
|
|
||||||
|
if (!deserializer->read(&reader->count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader->data = new T[reader->count];
|
||||||
|
|
||||||
|
for (int i = 0; i < reader->count; ++i) {
|
||||||
|
if (!deserializer->read(reader->data + i)) {
|
||||||
|
reader->clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
173
mc_serial.cpp
Normal file
173
mc_serial.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_serial.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Deserializer
|
||||||
|
//
|
||||||
|
|
||||||
|
Deserializer::Deserializer(const Buffer* data) :
|
||||||
|
data_(data),
|
||||||
|
offset_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte* Deserializer::readRaw(int size) {
|
||||||
|
if (data_ == NULL || size > data_->bytes() - offset_) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte* data = static_cast<const byte*>(data_->data()) + offset_;
|
||||||
|
offset_ += size;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Deserializer::offset() const {
|
||||||
|
return offset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Deserializer::setOffset(int offset, bool relative) {
|
||||||
|
const int offsetNew = relative ? offset_ + offset : offset;
|
||||||
|
|
||||||
|
if (offsetNew >= 0 && offsetNew <= data_->bytes()) {
|
||||||
|
offset_ = offsetNew;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Serializer
|
||||||
|
//
|
||||||
|
|
||||||
|
Serializer::Serializer(Buffer* data) :
|
||||||
|
data_(data),
|
||||||
|
offset_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Serializer::writeRaw(const void* data, int size) {
|
||||||
|
if (data_ != NULL) {
|
||||||
|
data_->addToBack(static_cast<const byte*>(data), size);
|
||||||
|
offset_ += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Serializer::setOffset(int offset, bool relative) {
|
||||||
|
const int offsetNew = relative ? offset_ + offset : offset;
|
||||||
|
|
||||||
|
if (offsetNew >= 0 && offsetNew <= data_->bytes()) {
|
||||||
|
offset_ = offsetNew;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serializer::offset() const {
|
||||||
|
return offset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Serializers
|
||||||
|
//
|
||||||
|
|
||||||
|
bool serialize(Serializer* serializer, const Buffer& buffer) {
|
||||||
|
serializer->write(buffer.bytes());
|
||||||
|
serializer->writeRaw(buffer.data(), buffer.bytes());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deserialize(Deserializer* deserializer, Buffer* buffer) {
|
||||||
|
int count = 0;
|
||||||
|
if (!deserializer->read(&count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte* const data = deserializer->readRaw(count);
|
||||||
|
if (data == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->setData(data, count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool serialize(Serializer* serializer, const PacketHeader& packet) {
|
||||||
|
return
|
||||||
|
serializer->write(packet.magic) &&
|
||||||
|
serializer->write(packet.id) &&
|
||||||
|
serializer->write(packet.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deserialize(Deserializer* deserializer, PacketHeader* packet) {
|
||||||
|
return
|
||||||
|
deserializer->read(&packet->magic) &&
|
||||||
|
deserializer->read(&packet->id) &&
|
||||||
|
deserializer->read(&packet->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool serialize(Serializer* serializer, const PacketInvokeRequest& packet) {
|
||||||
|
return
|
||||||
|
serializer->write(packet.function) &&
|
||||||
|
serializer->write(packet.taskId) &&
|
||||||
|
serializer->write(packet.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deserialize(Deserializer* deserializer, PacketInvokeRequest* packet) {
|
||||||
|
return
|
||||||
|
deserializer->read(&packet->function) &&
|
||||||
|
deserializer->read(&packet->taskId) &&
|
||||||
|
deserializer->read(&packet->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool serialize(Serializer* serializer, const PacketInvokeReply& packet) {
|
||||||
|
return
|
||||||
|
serializer->write(packet.flags) &&
|
||||||
|
serializer->write(packet.taskId) &&
|
||||||
|
serializer->write(packet.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deserialize(Deserializer* deserializer, PacketInvokeReply* packet) {
|
||||||
|
return
|
||||||
|
deserializer->read(&packet->flags) &&
|
||||||
|
deserializer->read(&packet->taskId) &&
|
||||||
|
deserializer->read(&packet->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
136
mc_serial.hpp
Normal file
136
mc_serial.hpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Deserializer
|
||||||
|
//
|
||||||
|
|
||||||
|
class Deserializer {
|
||||||
|
public:
|
||||||
|
Deserializer(const Buffer* data);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool read (T* data);
|
||||||
|
const byte* readRaw (int size);
|
||||||
|
bool setOffset (int offset, bool relative);
|
||||||
|
int offset () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Buffer* data_;
|
||||||
|
int offset_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Serializer
|
||||||
|
//
|
||||||
|
|
||||||
|
class Serializer {
|
||||||
|
public:
|
||||||
|
Serializer(Buffer* data);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool write (const T& data);
|
||||||
|
bool writeRaw (const void* data, int size);
|
||||||
|
bool setOffset (int offset, bool relative);
|
||||||
|
int offset () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Buffer* data_;
|
||||||
|
int offset_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// ArrayWriter
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ArrayWriter {
|
||||||
|
public:
|
||||||
|
ArrayWriter(const T* data, int count) :
|
||||||
|
data(data),
|
||||||
|
count(count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* data;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// ArrayReader
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ArrayReader {
|
||||||
|
public:
|
||||||
|
ArrayReader() :
|
||||||
|
data(NULL),
|
||||||
|
count(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ArrayReader() {
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
|
data = NULL;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* data;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Standard serializers/deserializers
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool serialize (Serializer* serializer, const ArrayWriter<T>& writer);
|
||||||
|
template <typename T>
|
||||||
|
bool deserialize (Deserializer* deserializer, ArrayReader<T>* reader);
|
||||||
|
|
||||||
|
bool serialize (Serializer* serializer, const Buffer& buffer);
|
||||||
|
bool deserialize (Deserializer* deserializer, Buffer* buffer);
|
||||||
|
|
||||||
|
bool serialize (Serializer* serializer, const PacketHeader& packet);
|
||||||
|
bool deserialize (Deserializer* deserializer, PacketHeader* packet);
|
||||||
|
|
||||||
|
bool serialize (Serializer* serializer, const PacketInvokeRequest& packet);
|
||||||
|
bool deserialize (Deserializer* deserializer, PacketInvokeRequest* packet);
|
||||||
|
|
||||||
|
bool serialize (Serializer* serializer, const PacketInvokeReply& packet);
|
||||||
|
bool deserialize (Deserializer* deserializer, PacketInvokeReply* packet);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
169
mc_server.cpp
Normal file
169
mc_server.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_server.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Server
|
||||||
|
//
|
||||||
|
|
||||||
|
Server::Server() :
|
||||||
|
clientMax_(1),
|
||||||
|
clientActive_(CLIENT_ID_INVALID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::~Server() {
|
||||||
|
disconnectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::advance() {
|
||||||
|
advanceConnecting();
|
||||||
|
advanceDisconnecting();
|
||||||
|
advanceConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Binding* Server::binding() const {
|
||||||
|
return &binding_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding* Server::binding() {
|
||||||
|
return &binding_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::start(int serverPort, int clientsMax) {
|
||||||
|
stop();
|
||||||
|
|
||||||
|
if (server_.open() && server_.bind(serverPort) && server_.listen()) {
|
||||||
|
server_.setBlocking(false);
|
||||||
|
server_.setNagle(false);
|
||||||
|
clientMax_ = clientsMax;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::stop() {
|
||||||
|
disconnectAll();
|
||||||
|
clientMax_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::getClients(std::vector<ClientId>* clients) const {
|
||||||
|
for (ClientMap::const_iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
|
||||||
|
clients->push_back(iter->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::getClient(ClientId id, ClientData* data) const {
|
||||||
|
const ClientMap::const_iterator iter = clients_.find(id);
|
||||||
|
if (iter != clients_.end()) {
|
||||||
|
data->id = iter->first;
|
||||||
|
data->name = iter->second->socket.hostname();
|
||||||
|
data->protocol = &iter->second->protocol;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::disconnect(ClientId id) {
|
||||||
|
const ClientMap::iterator iter = clients_.find(id);
|
||||||
|
if (iter != clients_.end()) {
|
||||||
|
delete iter->second;
|
||||||
|
clients_.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::disconnectAll() {
|
||||||
|
for (ClientMap::iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
clients_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Server::clientCount() const {
|
||||||
|
return clients_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientId Server::clientActive() const {
|
||||||
|
return clientActive_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::advanceConnecting() {
|
||||||
|
if (clientMax_ == 0 || !server_.opened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket client;
|
||||||
|
if (!server_.accept(&client)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::pair<ClientId, ClientEntry*> entry(registerClientId(), new ClientEntry(&binding_));
|
||||||
|
const ClientMap::iterator iter = clients_.insert(entry).first;
|
||||||
|
iter->second->socket.set(client.release());
|
||||||
|
iter->second->socket.setNagle(false);
|
||||||
|
iter->second->socket.setBlocking(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::advanceDisconnecting() {
|
||||||
|
std::vector<ClientMap::iterator> clients;
|
||||||
|
for (ClientMap::iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
|
||||||
|
if (!iter->second->socket.connected()) {
|
||||||
|
clients.push_back(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<ClientMap::iterator>::iterator iter = clients.begin(); iter != clients.end(); ++iter) {
|
||||||
|
disconnect((*iter)->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::advanceConnected() {
|
||||||
|
ASSERT(clientActive_ == CLIENT_ID_INVALID);
|
||||||
|
|
||||||
|
for (ClientMap::iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
|
||||||
|
clientActive_ = iter->first;
|
||||||
|
iter->second->protocol.advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
clientActive_ = CLIENT_ID_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientId Server::registerClientId() {
|
||||||
|
static int s_id = CLIENT_ID_INVALID;
|
||||||
|
while (++s_id == CLIENT_ID_INVALID);
|
||||||
|
return static_cast<ClientId>(s_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
101
mc_server.hpp
Normal file
101
mc_server.hpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Types
|
||||||
|
//
|
||||||
|
|
||||||
|
enum ClientId {
|
||||||
|
CLIENT_ID_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClientData {
|
||||||
|
ClientData() :
|
||||||
|
id(CLIENT_ID_INVALID),
|
||||||
|
protocol(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientId id;
|
||||||
|
std::string name;
|
||||||
|
Protocol* protocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Server
|
||||||
|
//
|
||||||
|
|
||||||
|
class Server {
|
||||||
|
public:
|
||||||
|
Server();
|
||||||
|
~Server();
|
||||||
|
|
||||||
|
void advance ();
|
||||||
|
bool start (int serverPort, int clientsMax = 1);
|
||||||
|
void stop ();
|
||||||
|
void disconnect (ClientId id);
|
||||||
|
void disconnectAll ();
|
||||||
|
|
||||||
|
void getClients (std::vector<ClientId>* clients) const;
|
||||||
|
bool getClient (ClientId id, ClientData* data) const;
|
||||||
|
ClientId clientActive () const;
|
||||||
|
int clientCount () const;
|
||||||
|
const Binding* binding () const;
|
||||||
|
Binding* binding ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ClientEntry : public ClientData {
|
||||||
|
ClientEntry(Binding* binding) :
|
||||||
|
stream(&socket),
|
||||||
|
protocol(&stream, binding)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket socket;
|
||||||
|
Stream stream;
|
||||||
|
Protocol protocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
void advanceConnecting ();
|
||||||
|
void advanceConnected ();
|
||||||
|
void advanceDisconnecting ();
|
||||||
|
static ClientId registerClientId ();
|
||||||
|
|
||||||
|
typedef std::map<ClientId, ClientEntry*> ClientMap;
|
||||||
|
ClientMap clients_;
|
||||||
|
int clientMax_;
|
||||||
|
ClientId clientActive_;
|
||||||
|
Socket server_;
|
||||||
|
Binding binding_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
314
mc_socket.cpp
Normal file
314
mc_socket.cpp
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_socket.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constants
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
const int SOCKET_INVALID = -1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Socket
|
||||||
|
//
|
||||||
|
|
||||||
|
Socket::Socket() :
|
||||||
|
socket_(SOCKET_INVALID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket::~Socket() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::open() {
|
||||||
|
close();
|
||||||
|
socket_ = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
return opened();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::close() {
|
||||||
|
if (!opened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
closesocket(socket_);
|
||||||
|
#else
|
||||||
|
::close(socket_);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
socket_ = SOCKET_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Socket::release() {
|
||||||
|
const int temp = socket_;
|
||||||
|
socket_ = SOCKET_INVALID;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::set(int socket) {
|
||||||
|
close();
|
||||||
|
socket_ = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::setNagle(bool enable) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
const int value = enable ? 0 : 1;
|
||||||
|
const char* const valuePtr = reinterpret_cast<const char*>(&value);
|
||||||
|
|
||||||
|
setsockopt(
|
||||||
|
socket_,
|
||||||
|
IPPROTO_TCP,
|
||||||
|
TCP_NODELAY,
|
||||||
|
valuePtr,
|
||||||
|
sizeof(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::setBlocking(bool enable) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
unsigned long nonBlock = enable ? 0 : 1;
|
||||||
|
ioctlsocket(socket_, FIONBIO, &nonBlock);
|
||||||
|
#else
|
||||||
|
const int flagsOld = fcntl(socket_, F_GETFL);
|
||||||
|
const int flagsNew = enable ? flagsOld & ~O_NONBLOCK : flagsOld | O_NONBLOCK;
|
||||||
|
fcntl(socket_, F_SETFL, flagsNew);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::connect(const char name[], int port) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
long address = 0;
|
||||||
|
if (!resolve(name, &address)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in host = { 0 };
|
||||||
|
host.sin_port = htons(static_cast<unsigned short>(port));
|
||||||
|
host.sin_family = AF_INET;
|
||||||
|
host.sin_addr.s_addr = address;
|
||||||
|
|
||||||
|
const sockaddr* const hostPtr = reinterpret_cast<const sockaddr*>(&host);
|
||||||
|
if (::connect(socket_, hostPtr, sizeof(host)) == SOCKET_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::bind(int port) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
sockaddr_in host = { 0 };
|
||||||
|
host.sin_family = AF_INET;
|
||||||
|
host.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
host.sin_port = htons(static_cast<unsigned short>(port));
|
||||||
|
|
||||||
|
const sockaddr* const hostPtr = reinterpret_cast<const sockaddr*>(&host);
|
||||||
|
if (::bind(socket_, hostPtr, sizeof(host)) == SOCKET_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::listen(int backlog) {
|
||||||
|
ASSERT(opened());
|
||||||
|
return ::listen(socket_, backlog) != SOCKET_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::accept(Socket* socket) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
socket->close();
|
||||||
|
socket->socket_ = ::accept(socket_, 0, 0);
|
||||||
|
|
||||||
|
return socket->socket_ != SOCKET_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Socket::receive(void* buffer, int size) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return recv(
|
||||||
|
socket_,
|
||||||
|
static_cast<char *>(buffer),
|
||||||
|
size,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Socket::peek(void* buffer, int size) const {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return recv(
|
||||||
|
socket_,
|
||||||
|
static_cast<char *>(buffer),
|
||||||
|
size,
|
||||||
|
MSG_PEEK
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Socket::send(const void* buffer, int size) {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ::send(
|
||||||
|
socket_,
|
||||||
|
static_cast<const char*>(buffer),
|
||||||
|
size,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::wait(unsigned mask, int seconds) const {
|
||||||
|
ASSERT(opened());
|
||||||
|
|
||||||
|
fd_set readSet;
|
||||||
|
fd_set writeSet;
|
||||||
|
fd_set exceptSet;
|
||||||
|
|
||||||
|
fd_set* readSetUse = NULL;
|
||||||
|
fd_set* writeSetUse = NULL;
|
||||||
|
fd_set* exceptSetUse = NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4127)
|
||||||
|
#endif
|
||||||
|
if (IS_TRUE(mask & MASK_READ)) {
|
||||||
|
readSetUse = &readSet;
|
||||||
|
FD_ZERO(readSetUse);
|
||||||
|
FD_SET(socket_, readSetUse);
|
||||||
|
}
|
||||||
|
if (IS_TRUE(mask & MASK_WRITE)) {
|
||||||
|
writeSetUse = &writeSet;
|
||||||
|
FD_ZERO(writeSetUse);
|
||||||
|
FD_SET(socket_, writeSetUse);
|
||||||
|
}
|
||||||
|
if (IS_TRUE(mask & MASK_EXCEPT)) {
|
||||||
|
exceptSetUse = &exceptSet;
|
||||||
|
FD_ZERO(exceptSetUse);
|
||||||
|
FD_SET(socket_, exceptSetUse);
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
timeval timeoutVal = { 0 };
|
||||||
|
timeoutVal.tv_sec = seconds;
|
||||||
|
|
||||||
|
timeval* const timeoutPtr = seconds < 0 ? NULL : &timeoutVal;
|
||||||
|
const int result = select(
|
||||||
|
socket_ + 1,
|
||||||
|
readSetUse,
|
||||||
|
writeSetUse,
|
||||||
|
exceptSetUse,
|
||||||
|
timeoutPtr
|
||||||
|
);
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::opened() const {
|
||||||
|
return socket_ != SOCKET_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::connected() const {
|
||||||
|
if (!opened()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wait(MASK_READ, 0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte buffer = 0;
|
||||||
|
if (peek(&buffer, sizeof(buffer)) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Socket::hostname() const {
|
||||||
|
if (!opened()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in host = { 0 };
|
||||||
|
socklen_t hostSize = sizeof(host);
|
||||||
|
sockaddr* const hostPtr = reinterpret_cast<sockaddr*>(&host);
|
||||||
|
|
||||||
|
if (getsockname(socket_, hostPtr, &hostSize) == SOCKET_INVALID) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inet_ntoa(host.sin_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Socket::resolve(const char name[], long* address) {
|
||||||
|
if ((*address = inet_addr(name)) != INADDR_NONE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostent* const host = gethostbyname(name);
|
||||||
|
if (host == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*address = *reinterpret_cast<long*>(host->h_addr_list[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
74
mc_socket.hpp
Normal file
74
mc_socket.hpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Socket
|
||||||
|
//
|
||||||
|
|
||||||
|
class Socket {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
MASK_READ = 1 << 0,
|
||||||
|
MASK_WRITE = 1 << 1,
|
||||||
|
MASK_EXCEPT = 1 << 2
|
||||||
|
};
|
||||||
|
|
||||||
|
Socket();
|
||||||
|
~Socket();
|
||||||
|
|
||||||
|
bool open ();
|
||||||
|
void close ();
|
||||||
|
int release ();
|
||||||
|
void set (int socket);
|
||||||
|
void setNagle (bool enable);
|
||||||
|
void setBlocking (bool enable);
|
||||||
|
|
||||||
|
bool connect (const char name[], int port);
|
||||||
|
bool bind (int port);
|
||||||
|
bool listen (int backlog = 5);
|
||||||
|
bool accept (Socket* socket);
|
||||||
|
|
||||||
|
int receive (void* buffer, int size);
|
||||||
|
int peek (void* buffer, int size) const;
|
||||||
|
int send (const void* buffer, int size);
|
||||||
|
bool wait (unsigned mask, int seconds) const;
|
||||||
|
|
||||||
|
bool opened () const;
|
||||||
|
bool connected () const;
|
||||||
|
const char* hostname () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool resolve (const char name[], long* address);
|
||||||
|
|
||||||
|
int socket_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
72
mc_stream-inl.hpp
Normal file
72
mc_stream-inl.hpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Stream::State Stream::send(const T& packet) {
|
||||||
|
if (!socket_->connected()) {
|
||||||
|
return STATE_ERROR_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer buffTemp;
|
||||||
|
Serializer serializerTemp(&buffTemp);
|
||||||
|
serializerTemp.write(packet);
|
||||||
|
|
||||||
|
PacketHeader header;
|
||||||
|
header.magic = PACKET_CONST_MAGIC;
|
||||||
|
header.size = serializerTemp.offset();
|
||||||
|
header.id = T::Id;
|
||||||
|
|
||||||
|
Serializer serializer_send(&buffSend_);
|
||||||
|
serializer_send.write(header);
|
||||||
|
serializer_send.writeRaw(buffTemp.data(), buffTemp.bytes());
|
||||||
|
|
||||||
|
return STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Stream::State Stream::receive(T* packet) {
|
||||||
|
PacketHeader header;
|
||||||
|
int headerSize = 0;
|
||||||
|
|
||||||
|
const State state = peek(&header, &headerSize);
|
||||||
|
if (state != STATE_READY) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffRecv_.removeFromFront(NULL, headerSize);
|
||||||
|
|
||||||
|
Deserializer deserializer(&buffRecv_);
|
||||||
|
const bool success =
|
||||||
|
deserializer.read(packet) &&
|
||||||
|
deserializer.offset() == static_cast<int>(header.size);
|
||||||
|
|
||||||
|
buffRecv_.removeFromFront(NULL, header.size);
|
||||||
|
|
||||||
|
return success ? STATE_READY : STATE_ERROR_PROTOCOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
109
mc_stream.cpp
Normal file
109
mc_stream.cpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_stream.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Stream
|
||||||
|
//
|
||||||
|
|
||||||
|
Stream::Stream(Socket* socket) :
|
||||||
|
socket_(socket)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::State Stream::advance() {
|
||||||
|
if (!socket_->connected()) {
|
||||||
|
return STATE_ERROR_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffSend_.bytes() > 0 && socket_->wait(Socket::MASK_WRITE, 0)) {
|
||||||
|
const int bytesSent = socket_->send(
|
||||||
|
buffSend_.data(),
|
||||||
|
buffSend_.bytes()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (bytesSent <= 0) {
|
||||||
|
return STATE_ERROR_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffSend_.removeFromFront(NULL, bytesSent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket_->wait(Socket::MASK_READ, 0)) {
|
||||||
|
const int bytesReceived = socket_->receive(
|
||||||
|
buffNet_.data(),
|
||||||
|
buffNet_.bytes()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (bytesReceived <= 0) {
|
||||||
|
return STATE_ERROR_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffRecv_.addToBack(buffNet_.data(), bytesReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::reset() {
|
||||||
|
buffSend_.clear();
|
||||||
|
buffRecv_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::State Stream::peek(PacketHeader* header, int* headerSize) {
|
||||||
|
Deserializer deserializer(&buffRecv_);
|
||||||
|
if (!deserializer.read(header)) {
|
||||||
|
return STATE_PENDING_PACKET_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header->magic != PACKET_CONST_MAGIC) {
|
||||||
|
return STATE_ERROR_PROTOCOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*headerSize = deserializer.offset();
|
||||||
|
|
||||||
|
const int packetSize = static_cast<int>(header->size) + *headerSize;
|
||||||
|
if (buffRecv_.bytes() < packetSize) {
|
||||||
|
return STATE_PENDING_PACKET_BODY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Socket* Stream::socket() const {
|
||||||
|
return socket_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket* Stream::socket() {
|
||||||
|
return socket_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
67
mc_stream.hpp
Normal file
67
mc_stream.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Stream
|
||||||
|
//
|
||||||
|
|
||||||
|
class Stream {
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
STATE_READY,
|
||||||
|
STATE_PENDING_PACKET_HEADER,
|
||||||
|
STATE_PENDING_PACKET_BODY,
|
||||||
|
STATE_ERROR_PROTOCOL,
|
||||||
|
STATE_ERROR_CONNECTION
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream(Socket* socket);
|
||||||
|
|
||||||
|
State advance ();
|
||||||
|
void reset ();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
State send (const T& packet);
|
||||||
|
template <typename T>
|
||||||
|
State receive (T* packet);
|
||||||
|
State peek (PacketHeader* header, int* headerSize);
|
||||||
|
|
||||||
|
const Socket* socket () const;
|
||||||
|
Socket* socket ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Socket* socket_;
|
||||||
|
Buffer buffRecv_;
|
||||||
|
Buffer buffSend_;
|
||||||
|
Buffer buffNet_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
58
mc_token.cpp
Normal file
58
mc_token.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "metacall.hpp"
|
||||||
|
#include "mc_token.hpp"
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Token
|
||||||
|
//
|
||||||
|
|
||||||
|
Token::Token(const char value[]) :
|
||||||
|
value_(hash(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Token::Token(unsigned value) :
|
||||||
|
value_(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Token::operator unsigned() const {
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Token::hash(const char str[]) {
|
||||||
|
unsigned hash = 5381;
|
||||||
|
for (const char* ptr = str; *ptr != 0; ++ptr) {
|
||||||
|
hash = (hash << 5) + hash + *ptr;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
49
mc_token.hpp
Normal file
49
mc_token.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace metacall {
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Token
|
||||||
|
//
|
||||||
|
|
||||||
|
class Token {
|
||||||
|
public:
|
||||||
|
Token(const char value[]);
|
||||||
|
Token(unsigned value);
|
||||||
|
|
||||||
|
operator unsigned() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static unsigned hash(const char str[]);
|
||||||
|
|
||||||
|
unsigned value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
60
metacall.hpp
Normal file
60
metacall.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011 Alex Yatskov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mc_common.hpp"
|
||||||
|
#include "mc_token.hpp"
|
||||||
|
#include "mc_buffer.hpp"
|
||||||
|
#include "mc_socket.hpp"
|
||||||
|
#include "mc_packet.hpp"
|
||||||
|
#include "mc_meta.hpp"
|
||||||
|
#include "mc_serial.hpp"
|
||||||
|
#include "mc_serial-inl.hpp"
|
||||||
|
#include "mc_functor.hpp"
|
||||||
|
#include "mc_binding.hpp"
|
||||||
|
#include "mc_binding-inl.hpp"
|
||||||
|
#include "mc_stream.hpp"
|
||||||
|
#include "mc_stream-inl.hpp"
|
||||||
|
#include "mc_protocol.hpp"
|
||||||
|
#include "mc_protocol-inl.hpp"
|
||||||
|
#include "mc_client.hpp"
|
||||||
|
#include "mc_server.hpp"
|
104
metacall.project
Normal file
104
metacall.project
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<CodeLite_Project Name="metacall" InternalType="Console">
|
||||||
|
<Description/>
|
||||||
|
<Dependencies/>
|
||||||
|
<VirtualDirectory Name="src">
|
||||||
|
<File Name="main.cpp"/>
|
||||||
|
<File Name="mc_socket.cpp"/>
|
||||||
|
<File Name="mc_socket.hpp"/>
|
||||||
|
<File Name="metacall.hpp"/>
|
||||||
|
<File Name="mc_buffer.cpp"/>
|
||||||
|
<File Name="mc_buffer.hpp"/>
|
||||||
|
<File Name="mc_packet.hpp"/>
|
||||||
|
<File Name="mc_stream.cpp"/>
|
||||||
|
<File Name="mc_stream.hpp"/>
|
||||||
|
<File Name="mc_stream-inl.hpp"/>
|
||||||
|
<File Name="mc_serial.hpp"/>
|
||||||
|
<File Name="mc_serial-inl.hpp"/>
|
||||||
|
<File Name="mc_serial.cpp"/>
|
||||||
|
<File Name="mc_meta.hpp"/>
|
||||||
|
<File Name="mc_functor.hpp"/>
|
||||||
|
<File Name="mc_binding-inl.hpp"/>
|
||||||
|
<File Name="mc_binding.hpp"/>
|
||||||
|
<File Name="mc_binding.cpp"/>
|
||||||
|
<File Name="mc_common.hpp"/>
|
||||||
|
<File Name="mc_protocol-inl.hpp"/>
|
||||||
|
<File Name="mc_protocol.cpp"/>
|
||||||
|
<File Name="mc_protocol.hpp"/>
|
||||||
|
<File Name="mc_client.cpp"/>
|
||||||
|
<File Name="mc_client.hpp"/>
|
||||||
|
<File Name="mc_server.cpp"/>
|
||||||
|
<File Name="mc_server.hpp"/>
|
||||||
|
<File Name="mc_token.cpp"/>
|
||||||
|
<File Name="mc_token.hpp"/>
|
||||||
|
</VirtualDirectory>
|
||||||
|
<Settings Type="Executable">
|
||||||
|
<GlobalSettings>
|
||||||
|
<Compiler Options="" C_Options="">
|
||||||
|
<IncludePath Value="."/>
|
||||||
|
</Compiler>
|
||||||
|
<Linker Options="">
|
||||||
|
<LibraryPath Value="."/>
|
||||||
|
</Linker>
|
||||||
|
<ResourceCompiler Options=""/>
|
||||||
|
</GlobalSettings>
|
||||||
|
<Configuration Name="Debug" CompilerType="gnu g++" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
|
||||||
|
<Compiler Options="-g" C_Options="-g" Required="yes" PreCompiledHeader="">
|
||||||
|
<IncludePath Value="."/>
|
||||||
|
</Compiler>
|
||||||
|
<Linker Options="" Required="yes"/>
|
||||||
|
<ResourceCompiler Options="" Required="no"/>
|
||||||
|
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
|
||||||
|
<Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>"/>
|
||||||
|
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
|
||||||
|
<PostConnectCommands/>
|
||||||
|
<StartupCommands/>
|
||||||
|
</Debugger>
|
||||||
|
<PreBuild/>
|
||||||
|
<PostBuild/>
|
||||||
|
<CustomBuild Enabled="no">
|
||||||
|
<RebuildCommand/>
|
||||||
|
<CleanCommand/>
|
||||||
|
<BuildCommand/>
|
||||||
|
<PreprocessFileCommand/>
|
||||||
|
<SingleFileCommand/>
|
||||||
|
<MakefileGenerationCommand/>
|
||||||
|
<ThirdPartyToolName>None</ThirdPartyToolName>
|
||||||
|
<WorkingDirectory/>
|
||||||
|
</CustomBuild>
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild/>
|
||||||
|
</AdditionalRules>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration Name="Release" CompilerType="gnu g++" DebuggerType="GNU gdb debugger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
|
||||||
|
<Compiler Options="" C_Options="" Required="yes" PreCompiledHeader="">
|
||||||
|
<IncludePath Value="."/>
|
||||||
|
</Compiler>
|
||||||
|
<Linker Options="-O2" Required="yes"/>
|
||||||
|
<ResourceCompiler Options="" Required="no"/>
|
||||||
|
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Release" Command="./$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
|
||||||
|
<Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>"/>
|
||||||
|
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
|
||||||
|
<PostConnectCommands/>
|
||||||
|
<StartupCommands/>
|
||||||
|
</Debugger>
|
||||||
|
<PreBuild/>
|
||||||
|
<PostBuild/>
|
||||||
|
<CustomBuild Enabled="no">
|
||||||
|
<RebuildCommand/>
|
||||||
|
<CleanCommand/>
|
||||||
|
<BuildCommand/>
|
||||||
|
<PreprocessFileCommand/>
|
||||||
|
<SingleFileCommand/>
|
||||||
|
<MakefileGenerationCommand/>
|
||||||
|
<ThirdPartyToolName>None</ThirdPartyToolName>
|
||||||
|
<WorkingDirectory/>
|
||||||
|
</CustomBuild>
|
||||||
|
<AdditionalRules>
|
||||||
|
<CustomPostBuild/>
|
||||||
|
<CustomPreBuild/>
|
||||||
|
</AdditionalRules>
|
||||||
|
</Configuration>
|
||||||
|
</Settings>
|
||||||
|
</CodeLite_Project>
|
12
metacall.workspace
Normal file
12
metacall.workspace
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<CodeLite_Workspace Name="metacall" Database="./metacall.tags">
|
||||||
|
<Project Name="metacall" Path="metacall.project" Active="Yes"/>
|
||||||
|
<BuildMatrix>
|
||||||
|
<WorkspaceConfiguration Name="Debug" Selected="yes">
|
||||||
|
<Project Name="metacall" ConfigName="Debug"/>
|
||||||
|
</WorkspaceConfiguration>
|
||||||
|
<WorkspaceConfiguration Name="Release" Selected="yes">
|
||||||
|
<Project Name="metacall" ConfigName="Release"/>
|
||||||
|
</WorkspaceConfiguration>
|
||||||
|
</BuildMatrix>
|
||||||
|
</CodeLite_Workspace>
|
Loading…
Reference in New Issue
Block a user