remotemono
RMonoVariant_Def.h
1 /*
2  Copyright 2020 David "Alemarius Nexus" Lerch
3 
4  This file is part of RemoteMono.
5 
6  RemoteMono is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  RemoteMono is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with RemoteMono. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #pragma once
21 
22 #include "../config.h"
23 
24 #include <cstdlib>
25 #include <stdint.h>
26 #include <string>
27 #include "RMonoTypes.h"
28 #include "RMonoHandle_Def.h"
29 
30 
31 
32 namespace remotemono
33 {
34 
35 
36 
37 class RMonoAPIBase;
38 
39 
40 
41 
71 {
72 public:
73  typedef RMonoVariant Self;
74 
75 public:
76  enum Type
77  {
78  TypeInvalid = 0,
79 
84  TypeValue = 1,
85 
90 
94  TypeRawPtr = 3
95  };
96 
115  {
123 
127  DirectionIn = 1 << 3,
128 
132  DirectionOut = 2 << 3,
133 
137  DirectionInOut = 3 << 3
138  };
139 
143  static inline const struct RawPtr {} rawPtr = {};
144 
146  {
147  public:
148  virtual RMonoObjectPtr getWrappedMonoObjectPtr() const = 0;
149  };
150 
151 private:
152  enum Flags
153  {
154  FlagMaskType = 0x0007,
155  FlagMaskDirection = 0x0018,
156 
167  FlagDisableAutoUnbox = 0x0100,
168 
173  FlagOwnMemory = 0x0200,
174 
180  FlagIsAlias = 0x0400
181  };
182 
183 public:
187  static constexpr size_t getMaxRequiredAlignment()
188  {
189  // TODO: I have no clue what value this should actually be.
190  return 16;
191  }
192 
193 public:
197  RMonoVariant() : flags(TypeInvalid) {}
198 
202  RMonoVariant(const Self& other)
203  {
204  copyFromOther(other);
205  }
206 
215  template <typename T, typename Enable = std::enable_if_t<!std::is_base_of_v<MonoObjectPtrWrapper, T>>>
217  : flags(TypeValue | FlagOwnMemory)
218  {
219  if constexpr(sizeof(T) <= sizeof(v.sdata)) {
220  *((T*) v.sdata) = val;
221  } else {
222  v.ddata = new char[sizeof(T)];
223  *((T*) v.ddata) = val;
224  }
225  v.size = sizeof(T);
226  }
227 
237  template <typename T>
238  RMonoVariant(T* val)
239  : flags(TypeValue)
240  {
241  v.ddata = val;
242  v.size = sizeof(T);
243  }
244 
268  RMonoVariant(void* data, size_t size, bool copy = false)
269  : flags(TypeValue)
270  {
271  if (data && copy) {
272  flags |= FlagOwnMemory;
273  if (size <= sizeof(v.sdata)) {
274  memcpy(v.sdata, data, size);
275  } else {
276  v.ddata = new char[size];
277  memcpy(v.ddata, data, size);
278  }
279  } else {
280  v.ddata = data;
281  }
282  v.size = size;
283  }
284 
293  RMonoVariant(const RMonoObjectPtr& v, bool autoUnbox = true)
294  : flags(TypeMonoObjectPtr | FlagOwnMemory | (autoUnbox ? 0 : FlagDisableAutoUnbox)), o(v) {}
295 
304  RMonoVariant(RMonoObjectPtr&& v, bool autoUnbox = true)
305  : flags(TypeMonoObjectPtr | FlagOwnMemory | (autoUnbox ? 0 : FlagDisableAutoUnbox)), o(v) {}
306 
316  RMonoVariant(RMonoObjectPtr* v, bool autoUnbox = true)
317  : flags(TypeMonoObjectPtr | (autoUnbox ? 0 : FlagDisableAutoUnbox)), op(v) {}
318 
319  RMonoVariant(const MonoObjectPtrWrapper& v, bool autoUnbox = true)
320  : flags(TypeMonoObjectPtr | FlagOwnMemory | (autoUnbox ? 0 : FlagDisableAutoUnbox)), o(v.getWrappedMonoObjectPtr()) {}
321 
327  RMonoVariant(std::nullptr_t) : flags(TypeRawPtr | FlagOwnMemory), p(0) {}
328 
337  explicit RMonoVariant(rmono_voidp v, RawPtr) : flags(TypeRawPtr | FlagOwnMemory), p(v) {}
338 
350  explicit RMonoVariant(rmono_voidp* v, RawPtr) : flags(TypeRawPtr), pp(v) {}
351 
352  ~RMonoVariant()
353  {
354  if (getType() == TypeValue && (flags & FlagOwnMemory) != 0 && !usesStaticValueData()) {
355  delete[] v.ddata;
356  }
357  }
358 
359 
360 
361 
365  Self& operator=(const Self& other)
366  {
367  if (this != &other) {
368  copyFromOther(other);
369  }
370  return *this;
371  }
372 
373 
382  Self forDirection(Direction dir) const { return Self(const_cast<Self*>(this), dir); }
383 
384 
388  Self in() const { return forDirection(DirectionIn); }
389 
393  Self out() const { return forDirection(DirectionOut); }
394 
398  Self inout() const { return forDirection(DirectionInOut); }
399 
400 
405  bool isValid() const { return getType() != TypeInvalid; }
406 
407 
411  Type getType() const { return (Type) (flags & FlagMaskType); }
412 
413  Direction getDirection() const { return (Direction) (flags & FlagMaskDirection); }
414  void setDirection(Direction dir) { flags = (flags & ~FlagMaskDirection) | dir; }
415 
419  void setAutoUnboxEnabled(bool autoUnbox)
420  {
421  if ((flags & FlagIsAlias) != 0) {
422  alias->setAutoUnboxEnabled(autoUnbox);
423  }
424  if (autoUnbox) {
425  flags &= ~FlagDisableAutoUnbox;
426  } else {
427  flags |= FlagDisableAutoUnbox;
428  }
429  }
430 
434  bool isAutoUnboxEnabled() const
435  {
436  return (flags & FlagDisableAutoUnbox) == 0;
437  }
438 
445  inline bool isNullPointer() const;
446 
447 
453  size_t getValueSize() const
454  {
455  assert(getType() == TypeValue);
456  if ((flags & FlagIsAlias) != 0) {
457  return alias->getValueSize();
458  }
459  return v.size;
460  }
461 
467  void* getValueData()
468  {
469  assert(getType() == TypeValue);
470  if ((flags & FlagIsAlias) != 0) {
471  return alias->getValueData();
472  }
473  return usesStaticValueData() ? v.sdata : v.ddata;
474  }
475 
481  const void* getValueData() const
482  {
483  assert(getType() == TypeValue);
484  if ((flags & FlagIsAlias) != 0) {
485  return alias->getValueData();
486  }
487  return usesStaticValueData() ? v.sdata : v.ddata;
488  }
489 
495  template <typename T>
496  T getValue() const
497  {
498  assert(getType() == TypeValue);
499  return *((T*) getValueData());
500  }
501 
508  {
509  assert(getType() == TypeMonoObjectPtr);
510  if ((flags & FlagIsAlias) != 0) {
511  return alias->getMonoObjectPtr();
512  }
513  if ((flags & FlagOwnMemory) != 0) {
514  return o;
515  } else {
516  return (op ? *op : RMonoObjectPtr());
517  }
518  }
519 
525  rmono_voidp getRawPtr() const
526  {
527  assert(getType() == TypeRawPtr);
528  if ((flags & FlagIsAlias) != 0) {
529  return alias->getRawPtr();
530  }
531  if ((flags & FlagOwnMemory) != 0) {
532  return p;
533  } else {
534  return (pp ? *pp : 0);
535  }
536  }
537 
538 
546  template <typename ABI>
547  size_t getRemoteMemorySize(ABI& abi, size_t& alignment) const;
548 
556  template <typename ABI>
557  void copyForRemoteMemory(ABI& abi, void* buf) const;
558 
566  template <typename ABI>
567  void updateFromRemoteMemory(ABI& abi, RMonoAPIBase& mono, void* buf);
568 
569 private:
571  : flags((other->flags & ~FlagMaskDirection) | FlagIsAlias | dir), alias(other) {}
572 
573  void copyFromOther(const Self& other)
574  {
575  if ((other.flags & FlagIsAlias) != 0) {
576  flags = other.flags;
577  alias = other.alias;
578  } else if (other.getType() == TypeMonoObjectPtr && (other.flags & FlagOwnMemory) != 0) {
579  flags = other.flags;
580  o = other.o;
581  } else if (other.getType() == TypeValue && (other.flags & FlagOwnMemory) != 0 && !other.usesStaticValueData()) {
582  v.size = other.v.size;
583  v.ddata = new char[v.size];
584  memcpy(v.ddata, other.v.ddata, v.size);
585  flags = other.flags;
586  } else {
587  memcpy(this, &other, sizeof(Self));
588  }
589  }
590 
591  bool usesStaticValueData() const
592  {
593  if ((flags & FlagIsAlias) != 0) {
594  return alias->usesStaticValueData();
595  }
596  return ((flags & FlagOwnMemory) != 0) && v.size <= sizeof(v.sdata);
597  }
598 
599 private:
600  uint16_t flags;
601 
602  union {
603  struct {
604  union
605  {
606  char sdata[32];
607  void* ddata;
608  };
609  size_t size;
610  } v;
611  RMonoObjectPtr* op;
612  rmono_voidp p;
613  rmono_voidp* pp;
614  RMonoVariant* alias;
615  };
616  RMonoObjectPtr o;
617 };
618 
619 
620 };
621 
622 
623 
624 
625 
626 #include "RMonoVariant_Impl.h"
remotemono::RMonoVariant::Direction
Direction
Definition: RMonoVariant_Def.h:115
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(const Self &other)
Definition: RMonoVariant_Def.h:202
remotemono::RMonoVariant::DirectionInOut
@ DirectionInOut
Definition: RMonoVariant_Def.h:137
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(RMonoObjectPtr *v, bool autoUnbox=true)
Definition: RMonoVariant_Def.h:316
remotemono::RMonoVariant::inout
Self inout() const
Definition: RMonoVariant_Def.h:398
remotemono::RMonoVariant::in
Self in() const
Definition: RMonoVariant_Def.h:388
remotemono::RMonoVariant::isNullPointer
bool isNullPointer() const
Definition: RMonoVariant_Impl.h:37
remotemono::RMonoVariant::getMaxRequiredAlignment
static constexpr size_t getMaxRequiredAlignment()
Definition: RMonoVariant_Def.h:187
remotemono::RMonoVariant::TypeMonoObjectPtr
@ TypeMonoObjectPtr
Definition: RMonoVariant_Def.h:89
remotemono::RMonoVariant::MonoObjectPtrWrapper
Definition: RMonoVariant_Def.h:146
remotemono::RMonoVariant::Type
Type
Definition: RMonoVariant_Def.h:77
remotemono::RMonoAPIBase
Definition: RMonoAPIBase_Def.h:43
remotemono::RMonoVariant::getValue
T getValue() const
Definition: RMonoVariant_Def.h:496
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(RMonoObjectPtr &&v, bool autoUnbox=true)
Definition: RMonoVariant_Def.h:304
remotemono::RMonoObjectHandle< RMonoObjectPtrRaw >
remotemono::RMonoVariant::copyForRemoteMemory
void copyForRemoteMemory(ABI &abi, void *buf) const
Definition: RMonoVariant_Impl.h:115
remotemono::RMonoVariant::DirectionDefault
@ DirectionDefault
Definition: RMonoVariant_Def.h:122
remotemono::RMonoVariant::getValueSize
size_t getValueSize() const
Definition: RMonoVariant_Def.h:453
remotemono::RMonoVariant::getRemoteMemorySize
size_t getRemoteMemorySize(ABI &abi, size_t &alignment) const
Definition: RMonoVariant_Impl.h:61
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(rmono_voidp v, RawPtr)
Definition: RMonoVariant_Def.h:337
remotemono::RMonoVariant::isAutoUnboxEnabled
bool isAutoUnboxEnabled() const
Definition: RMonoVariant_Def.h:434
remotemono::RMonoVariant::updateFromRemoteMemory
void updateFromRemoteMemory(ABI &abi, RMonoAPIBase &mono, void *buf)
Definition: RMonoVariant_Impl.h:143
remotemono::RMonoVariant::DirectionIn
@ DirectionIn
Definition: RMonoVariant_Def.h:127
remotemono::RMonoVariant::RMonoVariant
RMonoVariant()
Definition: RMonoVariant_Def.h:197
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(void *data, size_t size, bool copy=false)
Definition: RMonoVariant_Def.h:268
remotemono::RMonoVariant::forDirection
Self forDirection(Direction dir) const
Definition: RMonoVariant_Def.h:382
remotemono::RMonoVariant::isValid
bool isValid() const
Definition: RMonoVariant_Def.h:405
remotemono::RMonoVariant::getValueData
const void * getValueData() const
Definition: RMonoVariant_Def.h:481
remotemono::RMonoVariant::TypeRawPtr
@ TypeRawPtr
Definition: RMonoVariant_Def.h:94
remotemono::RMonoVariant::getValueData
void * getValueData()
Definition: RMonoVariant_Def.h:467
remotemono::RMonoVariant::getType
Type getType() const
Definition: RMonoVariant_Def.h:411
remotemono::RMonoVariant::getMonoObjectPtr
RMonoObjectPtr getMonoObjectPtr() const
Definition: RMonoVariant_Def.h:507
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(rmono_voidp *v, RawPtr)
Definition: RMonoVariant_Def.h:350
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(T *val)
Definition: RMonoVariant_Def.h:238
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(T val)
Definition: RMonoVariant_Def.h:216
remotemono::RMonoVariant::setAutoUnboxEnabled
void setAutoUnboxEnabled(bool autoUnbox)
Definition: RMonoVariant_Def.h:419
remotemono::RMonoVariant::DirectionOut
@ DirectionOut
Definition: RMonoVariant_Def.h:132
remotemono::RMonoVariant::TypeValue
@ TypeValue
Definition: RMonoVariant_Def.h:84
remotemono::RMonoVariant::operator=
Self & operator=(const Self &other)
Definition: RMonoVariant_Def.h:365
remotemono::RMonoVariant
Definition: RMonoVariant_Def.h:71
remotemono::RMonoVariant::out
Self out() const
Definition: RMonoVariant_Def.h:393
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(std::nullptr_t)
Definition: RMonoVariant_Def.h:327
remotemono::RMonoVariant::RMonoVariant
RMonoVariant(const RMonoObjectPtr &v, bool autoUnbox=true)
Definition: RMonoVariant_Def.h:293
remotemono::RMonoVariant::getRawPtr
rmono_voidp getRawPtr() const
Definition: RMonoVariant_Def.h:525