OOP.hh 5.63 KB
Newer Older
1
/******************************************************************************
balaskoa's avatar
balaskoa committed
2
 * Copyright (c) 2000-2020 Ericsson Telecom AB
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Baranyi, Botond
 *
 ******************************************************************************/

#ifndef OOP_HH
#define OOP_HH

#include "Universal_charstring.hh"
17
#include "Logger.hh"
18
19
20
21
22

// OBJECT
// ------

class OBJECT {
23
24
private:
  size_t ref_count;
25
26
  boolean destructor; // true, if the destructor is currently running;
  // also makes sure the object is not deleted again when inside the destructor
27
28
29
30
  
  OBJECT(const OBJECT&); // copy disabled
  OBJECT operator=(const OBJECT&); // assignment disabled
  boolean operator==(const OBJECT&); // equality operator disabled
31
public:
32
  OBJECT(): ref_count(0), destructor(FALSE) {}
33
34
35
36
37
38
39
40
  virtual ~OBJECT() {
    if (ref_count != 0) {
      TTCN_error("Internal error: deleting an object with %lu reference(s) left.", ref_count);
    }
  }
  void add_ref() { ++ref_count; }
  boolean remove_ref() {
    --ref_count;
41
42
43
44
45
    if (destructor) {
      return FALSE;
    }
    destructor = ref_count == 0;
    return destructor;
46
  }
47
  virtual void log() const {
48
    TTCN_Logger::log_event_str("object: { }");
49
  }
50
51
52
  virtual UNIVERSAL_CHARSTRING toString() {
    return UNIVERSAL_CHARSTRING("Object");
  }
53
54
55
56
57
58
59
};

// OBJECT_REF
// ----------

template <typename T>
class OBJECT_REF {
60
61
62
63
  template <typename T2>
  friend boolean operator==(null_type, const OBJECT_REF<T2>& right_val);
  template <typename T2>
  friend boolean operator!=(null_type, const OBJECT_REF<T2>& right_val);
64
private:
65
  T* ptr; // NULL if it's a null reference
66
67
  
public:
68
69
70
  OBJECT_REF(): ptr(NULL) {} // constructor with no parameters

  OBJECT_REF(null_type): ptr(NULL) {} // constructor for null reference
71
  
72
73
  OBJECT_REF(T* p_ptr): ptr(p_ptr) { // constructor for new value (.create)
    ptr->add_ref();
74
75
  }
  
76
77
78
  OBJECT_REF(const OBJECT_REF<T>& p_other): ptr(p_other.ptr) { // copy constructor
    if (ptr != NULL) {
      ptr->add_ref();
79
80
81
    }
  }
  
82
83
84
85
86
87
88
89
90
91
92
93
94
  template <typename T2>
  OBJECT_REF(OBJECT_REF<T2>& p_other) {
    if (p_other != NULL_VALUE) {
      ptr = dynamic_cast<T*>(*p_other);
      if (ptr != NULL) {
        ptr->add_ref();
      }
      else {
        TTCN_error("Invalid dynamic type of initial value.");
      }
    }
  }
  
95
96
97
98
99
100
101
102
103
  void clean_up() {
    if (ptr != NULL) {
      if (ptr->remove_ref()) {
        delete ptr;
      }
      ptr = NULL;
    }
  }
  
104
105
106
107
108
109
  ~OBJECT_REF() {
    clean_up();
  }
  
  OBJECT_REF& operator=(null_type) { // assignment operator for null reference
    clean_up();
110
    return *this;
111
112
113
114
  }
  
  OBJECT_REF& operator=(const OBJECT_REF<T>& p_other) { // assignment operator for actual reference
    clean_up();
115
116
117
    if (p_other.ptr != NULL) {
      ptr = p_other.ptr;
      ptr->add_ref();
118
119
120
121
    }
    return *this;
  }
  
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  template <typename T2>
  OBJECT_REF& operator=(OBJECT_REF<T2>& p_other) {
    clean_up();
    if (p_other != NULL_VALUE) {
      ptr = dynamic_cast<T*>(*p_other);
      if (ptr != NULL) {
        ptr->add_ref();
      }
      else {
        TTCN_error("Invalid dynamic type of assigned value.");
      }
    }
    return *this;
  }
  
137
138
  boolean operator==(null_type) const { // equality operator (with null reference)
    return ptr == NULL;
139
140
  }
  
141
142
143
144
145
146
147
148
149
150
  boolean operator!=(null_type) const { // inequality operator (with null reference)
    return ptr != NULL;
  }
  
  boolean operator==(const OBJECT_REF<T>& p_other) const { // equality operator (with actual reference)
    return ptr == p_other.ptr;
  }
  
  boolean operator!=(const OBJECT_REF<T>& p_other) const { // inequality operator (with actual reference)
    return ptr != p_other.ptr;
151
152
153
  }
  
  T* operator*() { // de-referencing operator
154
155
    if (ptr != NULL) {
      return ptr;
156
157
158
159
160
    }
    TTCN_error("Accessing a null reference.");
  }
  
  T* operator->() { // de-referencing operator (for methods)
161
162
    if (ptr != NULL) {
      return ptr;
163
164
165
166
167
    }
    TTCN_error("Accessing a null reference.");
  }
  
  const T* operator->() const { // de-referencing operator (for constant methods)
168
169
    if (ptr != NULL) {
      return ptr;
170
171
172
    }
    TTCN_error("Accessing a null reference.");
  }
173
174
175
176
177
178
179
180
181
  
  void log() const {
    if (ptr == NULL) {
      TTCN_Logger::log_event_str("null");
    }
    else {
      ptr->log();
    }
  }
182
183
184
185
186
187
188
189
190
191
192
193
  
  boolean is_bound() const {
    return ptr != NULL;
  }
  
  boolean is_value() const {
    return ptr != NULL;
  }
  
  boolean is_present() const {
    return ptr != NULL;
  }
194
195
};

196
197
198
199
200
201
202
203
204
205
template<typename T>
boolean operator==(null_type, const OBJECT_REF<T>& right_val) { // equality operator (with null reference, inverted)
  return right_val.ptr == NULL;
}

template<typename T>
boolean operator!=(null_type, const OBJECT_REF<T>& right_val) { // inequality operator (with null reference, inverted)
  return right_val.ptr != NULL;
}

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// EXCEPTION
// ---------

template<typename T, int type_id>
class EXCEPTION {
public:
  struct exception_struct {
    T* val_ptr;
    size_t ref_count;
  };
private:
  exception_struct* ex_ptr;
  EXCEPTION operator=(const EXCEPTION&); // assignment disabled
public:
  EXCEPTION(T* p_value): ex_ptr(new exception_struct) {
    ex_ptr->val_ptr = p_value;
    ex_ptr->ref_count = 1;
  }
  EXCEPTION(const EXCEPTION& p): ex_ptr(p.ex_ptr) {
    ++ex_ptr->ref_count;
  }
  ~EXCEPTION() {
    --ex_ptr->ref_count;
    if (ex_ptr->ref_count == 0) {
      delete ex_ptr->val_ptr;
      delete ex_ptr;
    }
  }
  T& operator()() { return *ex_ptr->val_ptr; }
};

#endif /* OOP_HH */