blob: 7900953804af5f031e39be70e8869801e3bcc3f4 [file] [log] [blame]
/* Copyright (c) 2021, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __GENERIC_PAYLOAD_H__
#define __GENERIC_PAYLOAD_H__
#include <errno.h>
#include <debug_handler.h>
#include <assert.h>
#include <functional>
#include <cstring>
// Do not define __CLASS__ for logging in shared utility header like this one
namespace sdm {
struct GenericPayload {
public:
GenericPayload():
type_size(0), payload(nullptr), array_size(0) {}
GenericPayload(const GenericPayload &in) {
type_size = 0;
payload = nullptr;
array_size = 0;
if (in.payload) {
display::DebugHandler::Get()->Error("GenericPayload::%s:New GenericPayload will not copy"
"payload data! Use CopyPayload on a new GenericPayload instance.", __FUNCTION__);
}
copy_constructed = true;
}
GenericPayload& operator=(const GenericPayload &) = delete;
template<typename A> int CopyPayload(const GenericPayload &in) {
if (sizeof(A) != in.type_size) {
return -EINVAL;
}
A* p = reinterpret_cast<A *>(in.payload);
type_size = sizeof(A);
array_size = in.array_size;
if (payload != nullptr) {
release();
}
A* p2 = nullptr;
if (array_size > 1) {
p2 = new A[array_size];
} else {
p2 = new A();
}
if (p2 == nullptr) {
return -ENOMEM;
}
*p2 = *p;
payload = reinterpret_cast<uint8_t *>(p2);
if (array_size > 1) {
release = std::function<void(void)>([p2]() -> void {delete [] p2;});
} else {
release = std::function<void(void)>([p2]() -> void {delete p2;});
}
return 0;
}
template<typename A> int CreatePayload(A *&p) {
if (payload) {
p = nullptr;
return -EALREADY;
}
p = new A();
if (p == nullptr) {
return -ENOMEM;
}
type_size = sizeof(A);
array_size = 1;
payload = reinterpret_cast<uint8_t *>(p);
release = std::function<void(void)>([p]() -> void {delete p;});
return 0;
}
template<typename A> int CreatePayload(A *&p, uint32_t sz) {
if (payload) {
p = nullptr;
return -EALREADY;
}
if (!sz) {
return -EINVAL;
}
p = new A[sz];
if (p == nullptr) {
return -ENOMEM;
}
type_size = sizeof(A);
array_size = sz;
payload = reinterpret_cast<uint8_t *>(p);
release = std::function<void(void)>([p]() -> void {delete [] p;});
return 0;
}
template<typename A> int GetPayload(A *&p, uint32_t *sz) const {
if ((sz == nullptr) || (sizeof(A) != type_size)) {
p = nullptr;
return -EINVAL;
}
p = reinterpret_cast<A *>(payload);
*sz = 0;
if (p == nullptr && copy_constructed) {
display::DebugHandler::Get()->Error("GenericPayload::%s:Payload was not properly"
"copied via CopyPayload", __FUNCTION__);
return -ENOMEM;
} else if (p == nullptr) {
display::DebugHandler::Get()->Error("GenericPayload::%s:Payload was not properly"
"created via CreatePayload", __FUNCTION__);
return -ENOMEM;
}
*sz = array_size;
return 0;
}
void DeletePayload() {
if (payload != nullptr) {
release();
}
type_size = 0;
payload = nullptr;
array_size = 0;
}
~GenericPayload() {
DeletePayload();
}
private:
uint32_t type_size;
uint8_t *payload;
uint32_t array_size;
std::function<void(void)> release;
bool copy_constructed = false;
};
} // namespace sdm
#endif // __GENERIC_PAYLOAD_H__