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