1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 21 #define _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1 22 23 #include <thrift/transport/TTransport.h> 24 25 namespace apache { 26 namespace thrift { 27 namespace transport { 28 29 /** 30 * Helper class that provides default implementations of TTransport methods. 31 * 32 * This class provides default implementations of read(), readAll(), write(), 33 * borrow() and consume(). 34 * 35 * In the TTransport base class, each of these methods simply invokes its 36 * virtual counterpart. This class overrides them to always perform the 37 * default behavior, without a virtual function call. 38 * 39 * The primary purpose of this class is to serve as a base class for 40 * TVirtualTransport, and prevent infinite recursion if one of its subclasses 41 * does not override the TTransport implementation of these methods. (Since 42 * TVirtualTransport::read_virt() calls read(), and TTransport::read() calls 43 * read_virt().) 44 */ 45 class TTransportDefaults : public TTransport { 46 public: 47 /* 48 * TTransport *_virt() methods provide reasonable default implementations. 49 * Invoke them non-virtually. 50 */ read(uint8_t * buf,uint32_t len)51 uint32_t read(uint8_t* buf, uint32_t len) { return this->TTransport::read_virt(buf, len); } readAll(uint8_t * buf,uint32_t len)52 uint32_t readAll(uint8_t* buf, uint32_t len) { return this->TTransport::readAll_virt(buf, len); } write(const uint8_t * buf,uint32_t len)53 void write(const uint8_t* buf, uint32_t len) { this->TTransport::write_virt(buf, len); } borrow(uint8_t * buf,uint32_t * len)54 const uint8_t* borrow(uint8_t* buf, uint32_t* len) { 55 return this->TTransport::borrow_virt(buf, len); 56 } consume(uint32_t len)57 void consume(uint32_t len) { this->TTransport::consume_virt(len); } 58 59 protected: TTransport(config)60 TTransportDefaults(std::shared_ptr<TConfiguration> config = nullptr) : TTransport(config) {} 61 }; 62 63 /** 64 * Helper class to provide polymorphism for subclasses of TTransport. 65 * 66 * This class implements *_virt() methods of TTransport, to call the 67 * non-virtual versions of these functions in the proper subclass. 68 * 69 * To define your own transport class using TVirtualTransport: 70 * 1) Derive your subclass from TVirtualTransport<your class> 71 * e.g: class MyTransport : public TVirtualTransport<MyTransport> { 72 * 2) Provide your own implementations of read(), readAll(), etc. 73 * These methods should be non-virtual. 74 * 75 * Transport implementations that need to use virtual inheritance when 76 * inheriting from TTransport cannot use TVirtualTransport. 77 * 78 * @author Chad Walters <chad@powerset.com> 79 */ 80 template <class Transport_, class Super_ = TTransportDefaults> 81 class TVirtualTransport : public Super_ { 82 public: 83 /* 84 * Implementations of the *_virt() functions, to call the subclass's 85 * non-virtual implementation function. 86 */ read_virt(uint8_t * buf,uint32_t len)87 uint32_t read_virt(uint8_t* buf, uint32_t len) override { 88 return static_cast<Transport_*>(this)->read(buf, len); 89 } 90 readAll_virt(uint8_t * buf,uint32_t len)91 uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { 92 return static_cast<Transport_*>(this)->readAll(buf, len); 93 } 94 write_virt(const uint8_t * buf,uint32_t len)95 void write_virt(const uint8_t* buf, uint32_t len) override { 96 static_cast<Transport_*>(this)->write(buf, len); 97 } 98 borrow_virt(uint8_t * buf,uint32_t * len)99 const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) override { 100 return static_cast<Transport_*>(this)->borrow(buf, len); 101 } 102 consume_virt(uint32_t len)103 void consume_virt(uint32_t len) override { static_cast<Transport_*>(this)->consume(len); } 104 105 /* 106 * Provide a default readAll() implementation that invokes 107 * read() non-virtually. 108 * 109 * Note: subclasses that use TVirtualTransport to derive from another 110 * transport implementation (i.e., not TTransportDefaults) should beware that 111 * this may override any non-default readAll() implementation provided by 112 * the parent transport class. They may need to redefine readAll() to call 113 * the correct parent implementation, if desired. 114 */ readAll(uint8_t * buf,uint32_t len)115 uint32_t readAll(uint8_t* buf, uint32_t len) { 116 auto* trans = static_cast<Transport_*>(this); 117 return ::apache::thrift::transport::readAll(*trans, buf, len); 118 } 119 120 protected: TVirtualTransport()121 TVirtualTransport() : Super_() {} 122 123 /* 124 * Templatized constructors, to allow arguments to be passed to the Super_ 125 * constructor. Currently we only support 0, 1, or 2 arguments, but 126 * additional versions can be added as needed. 127 */ 128 template <typename Arg_> TVirtualTransport(Arg_ const & arg)129 TVirtualTransport(Arg_ const& arg) 130 : Super_(arg) {} 131 132 template <typename Arg1_, typename Arg2_> TVirtualTransport(Arg1_ const & a1,Arg2_ const & a2)133 TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2) 134 : Super_(a1, a2) {} 135 }; 136 } 137 } 138 } // apache::thrift::transport 139 140 #endif // #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 141