just a fork

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Wed Dec 02 10:29:44 2015 +0000
Revision:
993:4d62b7967c11
Parent:
992:ca834f7ae8ed
Child:
1042:21a86ac7f5b1
Synchronized with git rev 12e27cd4
Author: Rohit Grover
Release 2.1.3
=============

* Improvements to CallChainOfFunctionPointerswithContext:
- add a `detach` function to be able to remove callbacks.
- detach function now return true if a function has been detached and
false otherwise.
- add a function call operator.
- use safe-bool idiom. see : http://www.artima.com/cppsource/safebool.html

* Add SafeBool class which allow to easily declare a safe bool operator in
c++03.

* Improvements to FunctionPointerWithContext:
- fix call propagation
- use safe bool idiom

* Add config file for generating Doxygen.

* Setup for onRadioNotification callback does not call initRadioNotification
anymore.

* GapAdvertisementData now handles replacement and appending of data fields
based on type. Some fields can be replaced with new values, and others
require the payload to be appended.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 710:b2e1a2660ec2 1 /* mbed Microcontroller Library
rgrover1 710:b2e1a2660ec2 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 710:b2e1a2660ec2 3 *
rgrover1 710:b2e1a2660ec2 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 710:b2e1a2660ec2 5 * you may not use this file except in compliance with the License.
rgrover1 710:b2e1a2660ec2 6 * You may obtain a copy of the License at
rgrover1 710:b2e1a2660ec2 7 *
rgrover1 710:b2e1a2660ec2 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 710:b2e1a2660ec2 9 *
rgrover1 710:b2e1a2660ec2 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 710:b2e1a2660ec2 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 710:b2e1a2660ec2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 710:b2e1a2660ec2 13 * See the License for the specific language governing permissions and
rgrover1 710:b2e1a2660ec2 14 * limitations under the License.
rgrover1 710:b2e1a2660ec2 15 */
rgrover1 710:b2e1a2660ec2 16
rgrover1 710:b2e1a2660ec2 17 #ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
rgrover1 710:b2e1a2660ec2 18 #define MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
rgrover1 710:b2e1a2660ec2 19
rgrover1 710:b2e1a2660ec2 20 #include <string.h>
rgrover1 993:4d62b7967c11 21 #include "SafeBool.h"
rgrover1 710:b2e1a2660ec2 22
rgrover1 710:b2e1a2660ec2 23 /** A class for storing and calling a pointer to a static or member void function
rgrover1 993:4d62b7967c11 24 * that takes a context.
rgrover1 710:b2e1a2660ec2 25 */
rgrover1 710:b2e1a2660ec2 26 template <typename ContextType>
rgrover1 993:4d62b7967c11 27 class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<ContextType> > {
rgrover1 710:b2e1a2660ec2 28 public:
rgrover1 710:b2e1a2660ec2 29 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
rgrover1 993:4d62b7967c11 30 typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_t;
rgrover1 710:b2e1a2660ec2 31 typedef void (*pvoidfcontext_t)(ContextType context);
rgrover1 710:b2e1a2660ec2 32
rgrover1 993:4d62b7967c11 33 /** Create a FunctionPointerWithContext, attaching a static function.
rgrover1 710:b2e1a2660ec2 34 *
rgrover1 993:4d62b7967c11 35 * @param function The void static function to attach (default is none).
rgrover1 710:b2e1a2660ec2 36 */
rgrover1 710:b2e1a2660ec2 37 FunctionPointerWithContext(void (*function)(ContextType context) = NULL) :
rgrover1 993:4d62b7967c11 38 _memberFunctionAndPointer(), _caller(NULL), _next(NULL) {
rgrover1 710:b2e1a2660ec2 39 attach(function);
rgrover1 710:b2e1a2660ec2 40 }
rgrover1 710:b2e1a2660ec2 41
rgrover1 993:4d62b7967c11 42 /** Create a FunctionPointerWithContext, attaching a member function.
rgrover1 710:b2e1a2660ec2 43 *
rgrover1 993:4d62b7967c11 44 * @param object The object pointer to invoke the member function on (the "this" pointer).
rgrover1 993:4d62b7967c11 45 * @param function The address of the void member function to attach.
rgrover1 710:b2e1a2660ec2 46 */
rgrover1 710:b2e1a2660ec2 47 template<typename T>
rgrover1 710:b2e1a2660ec2 48 FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) :
rgrover1 897:838e1375dbaa 49 _memberFunctionAndPointer(), _caller(NULL), _next(NULL) {
rgrover1 710:b2e1a2660ec2 50 attach(object, member);
rgrover1 710:b2e1a2660ec2 51 }
rgrover1 710:b2e1a2660ec2 52
rgrover1 993:4d62b7967c11 53 FunctionPointerWithContext(const FunctionPointerWithContext& that) :
rgrover1 993:4d62b7967c11 54 _memberFunctionAndPointer(that._memberFunctionAndPointer), _caller(that._caller), _next(NULL) {
rgrover1 993:4d62b7967c11 55 }
rgrover1 993:4d62b7967c11 56
rgrover1 993:4d62b7967c11 57 FunctionPointerWithContext& operator=(const FunctionPointerWithContext& that) {
rgrover1 993:4d62b7967c11 58 _memberFunctionAndPointer = that._memberFunctionAndPointer;
rgrover1 993:4d62b7967c11 59 _caller = that._caller;
rgrover1 993:4d62b7967c11 60 _next = NULL;
rgrover1 993:4d62b7967c11 61 return *this;
rgrover1 993:4d62b7967c11 62 }
rgrover1 993:4d62b7967c11 63
rgrover1 993:4d62b7967c11 64 /** Attach a static function.
rgrover1 710:b2e1a2660ec2 65 *
rgrover1 993:4d62b7967c11 66 * @param function The void static function to attach (default is none).
rgrover1 710:b2e1a2660ec2 67 */
rgrover1 710:b2e1a2660ec2 68 void attach(void (*function)(ContextType context) = NULL) {
rgrover1 710:b2e1a2660ec2 69 _function = function;
rgrover1 897:838e1375dbaa 70 _caller = functioncaller;
rgrover1 710:b2e1a2660ec2 71 }
rgrover1 710:b2e1a2660ec2 72
rgrover1 993:4d62b7967c11 73 /** Attach a member function.
rgrover1 710:b2e1a2660ec2 74 *
rgrover1 993:4d62b7967c11 75 * @param object The object pointer to invoke the member function on (the "this" pointer).
rgrover1 993:4d62b7967c11 76 * @param function The address of the void member function to attach.
rgrover1 710:b2e1a2660ec2 77 */
rgrover1 710:b2e1a2660ec2 78 template<typename T>
rgrover1 710:b2e1a2660ec2 79 void attach(T *object, void (T::*member)(ContextType context)) {
rgrover1 897:838e1375dbaa 80 _memberFunctionAndPointer._object = static_cast<void *>(object);
rgrover1 897:838e1375dbaa 81 memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member));
rgrover1 897:838e1375dbaa 82 _caller = &FunctionPointerWithContext::membercaller<T>;
rgrover1 710:b2e1a2660ec2 83 }
rgrover1 710:b2e1a2660ec2 84
rgrover1 993:4d62b7967c11 85 /** Call the attached static or member function; if there are chained
rgrover1 710:b2e1a2660ec2 86 * FunctionPointers their callbacks are invoked as well.
rgrover1 993:4d62b7967c11 87 * @Note: All chained callbacks stack up, so hopefully there won't be too
rgrover1 710:b2e1a2660ec2 88 * many FunctionPointers in a chain. */
rgrover1 993:4d62b7967c11 89 void call(ContextType context) const {
rgrover1 952:8a6c287de1be 90 _caller(this, context);
rgrover1 990:53ac0ac3aa39 91 }
rgrover1 990:53ac0ac3aa39 92
rgrover1 990:53ac0ac3aa39 93 /**
rgrover1 993:4d62b7967c11 94 * @brief Same as above
rgrover1 993:4d62b7967c11 95 */
rgrover1 993:4d62b7967c11 96 void operator()(ContextType context) const {
rgrover1 993:4d62b7967c11 97 call(context);
rgrover1 993:4d62b7967c11 98 }
rgrover1 993:4d62b7967c11 99
rgrover1 993:4d62b7967c11 100 /** Same as above, workaround for mbed os FunctionPointer implementation. */
rgrover1 993:4d62b7967c11 101 void call(ContextType context) {
rgrover1 993:4d62b7967c11 102 ((const FunctionPointerWithContext*) this)->call(context);
rgrover1 993:4d62b7967c11 103 }
rgrover1 993:4d62b7967c11 104
rgrover1 993:4d62b7967c11 105 typedef void (FunctionPointerWithContext::*bool_type)() const;
rgrover1 993:4d62b7967c11 106
rgrover1 993:4d62b7967c11 107 /**
rgrover1 993:4d62b7967c11 108 * implementation of safe bool operator
rgrover1 993:4d62b7967c11 109 */
rgrover1 993:4d62b7967c11 110 bool toBool() const {
rgrover1 993:4d62b7967c11 111 return (_function || _memberFunctionAndPointer._object);
rgrover1 993:4d62b7967c11 112 }
rgrover1 993:4d62b7967c11 113
rgrover1 993:4d62b7967c11 114 /**
rgrover1 993:4d62b7967c11 115 * Set up an external FunctionPointer as a next in the chain of related
rgrover1 710:b2e1a2660ec2 116 * callbacks. Invoking call() on the head FunctionPointer will invoke all
rgrover1 710:b2e1a2660ec2 117 * chained callbacks.
rgrover1 710:b2e1a2660ec2 118 *
rgrover1 710:b2e1a2660ec2 119 * Refer to 'CallChain' as an alternative.
rgrover1 710:b2e1a2660ec2 120 */
rgrover1 710:b2e1a2660ec2 121 void chainAsNext(pFunctionPointerWithContext_t next) {
rgrover1 710:b2e1a2660ec2 122 _next = next;
rgrover1 710:b2e1a2660ec2 123 }
rgrover1 710:b2e1a2660ec2 124
rgrover1 710:b2e1a2660ec2 125 pFunctionPointerWithContext_t getNext(void) const {
rgrover1 710:b2e1a2660ec2 126 return _next;
rgrover1 710:b2e1a2660ec2 127 }
rgrover1 710:b2e1a2660ec2 128
rgrover1 710:b2e1a2660ec2 129 pvoidfcontext_t get_function() const {
rgrover1 710:b2e1a2660ec2 130 return (pvoidfcontext_t)_function;
rgrover1 710:b2e1a2660ec2 131 }
rgrover1 710:b2e1a2660ec2 132
rgrover1 993:4d62b7967c11 133 friend bool operator==(const FunctionPointerWithContext& lhs, const FunctionPointerWithContext& rhs) {
rgrover1 993:4d62b7967c11 134 return rhs._caller == lhs._caller &&
rgrover1 993:4d62b7967c11 135 memcmp(
rgrover1 993:4d62b7967c11 136 &rhs._memberFunctionAndPointer,
rgrover1 993:4d62b7967c11 137 &lhs._memberFunctionAndPointer,
rgrover1 993:4d62b7967c11 138 sizeof(rhs._memberFunctionAndPointer)
rgrover1 993:4d62b7967c11 139 ) == 0;
rgrover1 993:4d62b7967c11 140 }
rgrover1 993:4d62b7967c11 141
rgrover1 710:b2e1a2660ec2 142 private:
rgrover1 710:b2e1a2660ec2 143 template<typename T>
rgrover1 993:4d62b7967c11 144 static void membercaller(cpFunctionPointerWithContext_t self, ContextType context) {
rgrover1 897:838e1375dbaa 145 if (self->_memberFunctionAndPointer._object) {
rgrover1 897:838e1375dbaa 146 T *o = static_cast<T *>(self->_memberFunctionAndPointer._object);
rgrover1 897:838e1375dbaa 147 void (T::*m)(ContextType);
rgrover1 897:838e1375dbaa 148 memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m));
rgrover1 897:838e1375dbaa 149 (o->*m)(context);
rgrover1 897:838e1375dbaa 150 }
rgrover1 897:838e1375dbaa 151 }
rgrover1 897:838e1375dbaa 152
rgrover1 993:4d62b7967c11 153 static void functioncaller(cpFunctionPointerWithContext_t self, ContextType context) {
rgrover1 897:838e1375dbaa 154 if (self->_function) {
rgrover1 897:838e1375dbaa 155 self->_function(context);
rgrover1 897:838e1375dbaa 156 }
rgrover1 710:b2e1a2660ec2 157 }
rgrover1 710:b2e1a2660ec2 158
rgrover1 897:838e1375dbaa 159 struct MemberFunctionAndPtr {
rgrover1 897:838e1375dbaa 160 /*
rgrover1 993:4d62b7967c11 161 * Forward declaration of a class and a member function to this class.
rgrover1 897:838e1375dbaa 162 * Because the compiler doesn't know anything about the forwarded member
rgrover1 897:838e1375dbaa 163 * function, it will always use the biggest size and the biggest alignment
rgrover1 897:838e1375dbaa 164 * that a member function can take for objects of type UndefinedMemberFunction.
rgrover1 897:838e1375dbaa 165 */
rgrover1 897:838e1375dbaa 166 class UndefinedClass;
rgrover1 897:838e1375dbaa 167 typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType);
rgrover1 897:838e1375dbaa 168
rgrover1 897:838e1375dbaa 169 void* _object;
rgrover1 897:838e1375dbaa 170 union {
rgrover1 897:838e1375dbaa 171 char _memberFunction[sizeof(UndefinedMemberFunction)];
rgrover1 897:838e1375dbaa 172 UndefinedMemberFunction _alignment;
rgrover1 897:838e1375dbaa 173 };
rgrover1 897:838e1375dbaa 174 };
rgrover1 897:838e1375dbaa 175
rgrover1 897:838e1375dbaa 176 union {
rgrover1 993:4d62b7967c11 177 pvoidfcontext_t _function; /**< Static function pointer - NULL if none attached */
rgrover1 897:838e1375dbaa 178 /**
rgrover1 897:838e1375dbaa 179 * object this pointer and pointer to member -
rgrover1 897:838e1375dbaa 180 * _memberFunctionAndPointer._object will be NULL if none attached
rgrover1 897:838e1375dbaa 181 */
rgrover1 993:4d62b7967c11 182 mutable MemberFunctionAndPtr _memberFunctionAndPointer;
rgrover1 897:838e1375dbaa 183 };
rgrover1 897:838e1375dbaa 184
rgrover1 993:4d62b7967c11 185 void (*_caller)(const FunctionPointerWithContext*, ContextType);
rgrover1 897:838e1375dbaa 186
rgrover1 993:4d62b7967c11 187 pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers. This
rgrover1 710:b2e1a2660ec2 188 * allows chaining function pointers without requiring
rgrover1 993:4d62b7967c11 189 * external memory to manage the chain. Refer to
rgrover1 710:b2e1a2660ec2 190 * 'CallChain' as an alternative. */
rgrover1 710:b2e1a2660ec2 191 };
rgrover1 710:b2e1a2660ec2 192
rgrover1 993:4d62b7967c11 193 /**
rgrover1 993:4d62b7967c11 194 * @brief Create a new FunctionPointerWithContext which bind an instance and a
rgrover1 993:4d62b7967c11 195 * a member function together.
rgrover1 993:4d62b7967c11 196 * @details This little helper is a just here to eliminate the need to write the
rgrover1 993:4d62b7967c11 197 * FunctionPointerWithContext type each time you want to create one by kicking
rgrover1 993:4d62b7967c11 198 * automatic type deduction of function templates. With this function, it is easy
rgrover1 993:4d62b7967c11 199 * to write only one entry point for functions which expect a FunctionPointer
rgrover1 993:4d62b7967c11 200 * in parameters.
rgrover1 993:4d62b7967c11 201 *
rgrover1 993:4d62b7967c11 202 * @param object to bound with member function
rgrover1 993:4d62b7967c11 203 * @param member The member function called
rgrover1 993:4d62b7967c11 204 * @return a new FunctionPointerWithContext
rgrover1 993:4d62b7967c11 205 */
rgrover1 993:4d62b7967c11 206 template<typename T, typename ContextType>
rgrover1 993:4d62b7967c11 207 FunctionPointerWithContext<ContextType> makeFunctionPointer(T *object, void (T::*member)(ContextType context))
rgrover1 993:4d62b7967c11 208 {
rgrover1 993:4d62b7967c11 209 return FunctionPointerWithContext<ContextType>(object, member);
rgrover1 993:4d62b7967c11 210 }
rgrover1 993:4d62b7967c11 211
rgrover1 710:b2e1a2660ec2 212 #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H