Panda3D
 All Classes Functions Variables Enumerations
internalName.cxx
1 // Filename: internalName.cxx
2 // Created by: masad (15Jul04)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pandabase.h"
16 #include "internalName.h"
17 #include "datagram.h"
18 #include "datagramIterator.h"
19 #include "bamReader.h"
20 #include "preparedGraphicsObjects.h"
21 
22 PT(InternalName) InternalName::_root;
23 PT(InternalName) InternalName::_error;
24 PT(InternalName) InternalName::_default;
25 PT(InternalName) InternalName::_vertex;
26 PT(InternalName) InternalName::_normal;
27 PT(InternalName) InternalName::_tangent;
28 PT(InternalName) InternalName::_binormal;
29 PT(InternalName) InternalName::_texcoord;
30 PT(InternalName) InternalName::_color;
31 PT(InternalName) InternalName::_rotate;
32 PT(InternalName) InternalName::_size;
33 PT(InternalName) InternalName::_aspect_ratio;
34 PT(InternalName) InternalName::_transform_blend;
35 PT(InternalName) InternalName::_transform_weight;
36 PT(InternalName) InternalName::_transform_index;
37 PT(InternalName) InternalName::_index;
38 PT(InternalName) InternalName::_world;
39 PT(InternalName) InternalName::_camera;
40 PT(InternalName) InternalName::_model;
41 PT(InternalName) InternalName::_view;
42 
43 TypeHandle InternalName::_type_handle;
44 TypeHandle InternalName::_texcoord_type_handle;
45 
46 #ifdef HAVE_PYTHON
47 InternalName::PyInternTable InternalName::_py_intern_table;
48 #endif
49 
50 InternalName::LiteralTable InternalName::_literal_table;
51 LightMutex InternalName::_literal_table_lock;
52 
53 ////////////////////////////////////////////////////////////////////
54 // Function: InternalName::Constructor
55 // Access: Private
56 // Description: Use make() to make a new InternalName instance.
57 ////////////////////////////////////////////////////////////////////
58 InternalName::
59 InternalName(InternalName *parent, const string &basename) :
60  _parent(parent),
61  _basename(basename)
62 {
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: InternalName::Destructor
67 // Access: Published, Virtual
68 // Description:
69 ////////////////////////////////////////////////////////////////////
70 InternalName::
71 ~InternalName() {
72 #ifndef NDEBUG
73  if (_parent != (const InternalName *)NULL) {
74  // unref() should have removed us from our parent's table already.
75  LightMutexHolder holder(_parent->_name_table_lock);
76  NameTable::iterator ni = _parent->_name_table.find(_basename);
77  nassertv(ni == _parent->_name_table.end());
78  }
79 #endif
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: InternalName::unref
84 // Access: Published, Virtual
85 // Description: This method overrides ReferenceCount::unref() to
86 // clear the pointer from its parent's table when
87 // its reference count goes to zero.
88 ////////////////////////////////////////////////////////////////////
89 bool InternalName::
90 unref() const {
91  if (_parent == (const InternalName *)NULL) {
92  // No parent; no problem. This is the root InternalName.
93  // Actually, this probably shouldn't be destructing, but I guess
94  // it might at application shutdown.
96  }
97 
98  LightMutexHolder holder(_parent->_name_table_lock);
99 
100  if (ReferenceCount::unref()) {
101  return true;
102  }
103 
104  // The reference count has just reached zero.
105  NameTable::iterator ni = _parent->_name_table.find(_basename);
106  nassertr(ni != _parent->_name_table.end(), false);
107  _parent->_name_table.erase(ni);
108 
109  return false;
110 }
111 
112 ////////////////////////////////////////////////////////////////////
113 // Function: InternalName::append
114 // Access: Published
115 // Description: Constructs a new InternalName based on this name,
116 // with the indicated string following it. This is a
117 // cheaper way to construct a hierarchical name than
118 // InternalName::make(parent->get_name() + ".basename").
119 ////////////////////////////////////////////////////////////////////
120 PT(InternalName) InternalName::
121 append(const string &name) {
123 
124  if (name.empty()) {
125  return this;
126  }
127 
128  size_t dot = name.rfind('.');
129  if (dot != string::npos) {
130  return append(name.substr(0, dot))->append(name.substr(dot + 1));
131  }
132 
133  LightMutexHolder holder(_name_table_lock);
134 
135  NameTable::iterator ni = _name_table.find(name);
136  if (ni != _name_table.end()) {
137  return (*ni).second;
138  }
139 
140  InternalName *internal_name = new InternalName(this, name);
141  _name_table[name] = internal_name;
142  return internal_name;
143 }
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: InternalName::get_name
147 // Access: Published
148 // Description: Returns the complete name represented by the
149 // InternalName and all of its parents.
150 ////////////////////////////////////////////////////////////////////
151 string InternalName::
152 get_name() const {
153  if (_parent == get_root()) {
154  return _basename;
155 
156  } else if (_parent == (InternalName *)NULL) {
157  return string();
158 
159  } else {
160  return _parent->get_name() + "." + _basename;
161  }
162 }
163 
164 ////////////////////////////////////////////////////////////////////
165 // Function: InternalName::join
166 // Access: Published
167 // Description: Like get_name, but uses a custom separator instead
168 // of ".".
169 ////////////////////////////////////////////////////////////////////
170 string InternalName::
171 join(const string &sep) const {
172  if (_parent == get_root()) {
173  return _basename;
174 
175  } else if (_parent == (InternalName *)NULL) {
176  return string();
177 
178  } else {
179  return _parent->join(sep) + sep + _basename;
180  }
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: InternalName::find_ancestor
185 // Access: Published
186 // Description: Returns the index of the ancestor with the indicated
187 // basename, or -1 if no ancestor has that basename.
188 // Returns 0 if this name has the basename.
189 //
190 // This index value may be passed to get_ancestor() or
191 // get_net_basename() to retrieve more information about
192 // the indicated name.
193 ////////////////////////////////////////////////////////////////////
194 int InternalName::
195 find_ancestor(const string &basename) const {
197 
198  if (_basename == basename) {
199  return 0;
200 
201  } else if (_parent != (InternalName *)NULL) {
202  int index = _parent->find_ancestor(basename);
203  if (index >= 0) {
204  return index + 1;
205  }
206  }
207 
208  return -1;
209 }
210 
211 ////////////////////////////////////////////////////////////////////
212 // Function: InternalName::get_ancestor
213 // Access: Published
214 // Description: Returns the ancestor with the indicated index number.
215 // 0 is this name itself, 1 is the name's parent, 2 is
216 // the parent's parent, and so on. If there are not
217 // enough ancestors, returns the root InternalName.
218 ////////////////////////////////////////////////////////////////////
219 const InternalName *InternalName::
220 get_ancestor(int n) const {
222 
223  if (n == 0) {
224  return this;
225 
226  } else if (_parent != (InternalName *)NULL) {
227  return _parent->get_ancestor(n - 1);
228 
229  } else {
230  return get_root();
231  }
232 }
233 
234 ////////////////////////////////////////////////////////////////////
235 // Function: InternalName::get_top
236 // Access: Published
237 // Description: Returns the oldest ancestor in the InternalName's
238 // chain, not counting the root. This will be the first
239 // name in the string, e.g. "texcoord.foo.bar" will
240 // return the InternalName "texcoord".
241 ////////////////////////////////////////////////////////////////////
242 const InternalName *InternalName::
243 get_top() const {
245 
246  if (_parent != (InternalName *)NULL && _parent != get_root()) {
247  return _parent->get_top();
248  }
249  return this;
250 }
251 
252 ////////////////////////////////////////////////////////////////////
253 // Function: InternalName::get_net_basename
254 // Access: Published
255 // Description: Returns the basename of this name prefixed by the
256 // indicated number of ancestors. 0 is this name's
257 // basename, 1 is parent.basename, 2 is
258 // grandparent.parent.basename, and so on.
259 ////////////////////////////////////////////////////////////////////
260 string InternalName::
261 get_net_basename(int n) const {
262  if (n < 0) {
263  return "";
264 
265  } else if (n == 0) {
266  return _basename;
267 
268  } else if (_parent != (InternalName *)NULL && _parent != get_root()) {
269  return _parent->get_net_basename(n - 1) + "." + _basename;
270 
271  } else {
272  return _basename;
273  }
274 }
275 
276 ////////////////////////////////////////////////////////////////////
277 // Function: InternalName::output
278 // Access: Published
279 // Description:
280 ////////////////////////////////////////////////////////////////////
281 void InternalName::
282 output(ostream &out) const {
283  if (_parent == get_root()) {
284  out << _basename;
285 
286  } else if (_parent == (InternalName *)NULL) {
287  out << "(root)";
288 
289  } else {
290  _parent->output(out);
291  out << '.' << _basename;
292  }
293 }
294 
295 ////////////////////////////////////////////////////////////////////
296 // Function: InternalName::register_with_read_factory
297 // Access: Public, Static
298 // Description: Factory method to generate a InternalName object
299 ////////////////////////////////////////////////////////////////////
300 void InternalName::
301 register_with_read_factory() {
302  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
303  BamReader::get_factory()->register_factory(_texcoord_type_handle, make_texcoord_from_bam);
304 }
305 
306 ////////////////////////////////////////////////////////////////////
307 // Function: InternalName::finalize
308 // Access: Public, Virtual
309 // Description: Called by the BamReader to perform any final actions
310 // needed for setting up the object after all objects
311 // have been read and all pointers have been completed.
312 ////////////////////////////////////////////////////////////////////
313 void InternalName::
314 finalize(BamReader *) {
315  // Unref the pointer that we explicitly reffed in make_from_bam().
316  unref();
317 
318  // We should never get back to zero after unreffing our own count,
319  // because we expect to have been stored in a pointer somewhere. If
320  // we do get to zero, it's a memory leak; the way to avoid this is
321  // to call unref_delete() above instead of unref(), but this is
322  // dangerous to do from within a virtual function.
323  nassertv(get_ref_count() != 0);
324 }
325 
326 ////////////////////////////////////////////////////////////////////
327 // Function: InternalName::make
328 // Access: Published, Static
329 // Description: Make using a string and an integer. Concatenates
330 // the two.
331 ////////////////////////////////////////////////////////////////////
332 PT(InternalName) InternalName::
333 make(const string &name, int index) {
334  std::ostringstream full;
335  full << name << index;
336  return make(full.str());
337 }
338 
339 ////////////////////////////////////////////////////////////////////
340 // Function: InternalName::make_from_bam
341 // Access: Protected, Static
342 // Description: This function is called by the BamReader's factory
343 // when a new object of type InternalName is encountered
344 // in the Bam file. It should create the InternalName
345 // and extract its information from the file.
346 ////////////////////////////////////////////////////////////////////
347 TypedWritable *InternalName::
348 make_from_bam(const FactoryParams &params) {
349  // The process of making a InternalName is slightly
350  // different than making other Writable objects.
351  // That is because all creation of InternalNames should
352  // be done through the make() constructor.
353  DatagramIterator scan;
354  BamReader *manager;
355 
356  parse_params(params, scan, manager);
357 
358  // The name is the only thing written to the data stream.
359  string name = scan.get_string();
360 
361  // Make a new InternalName with that name (or get the previous one
362  // if there is one already).
363  PT(InternalName) me = make(name);
364 
365  // But now we have a problem, since we have to hold the reference
366  // count and there's no way to return a TypedWritable while still
367  // holding the reference count! We work around this by explicitly
368  // upping the count, and also setting a finalize() callback to down
369  // it later.
370  me->ref();
371  manager->register_finalize(me);
372 
373  return me.p();
374 }
375 
376 ////////////////////////////////////////////////////////////////////
377 // Function: InternalName::make_texcoord_from_bam
378 // Access: Protected, Static
379 // Description: This is a temporary method; it exists only to support
380 // old bam files (4.11 through 4.17) generated before we
381 // renamed this class from TexCoordName to InternalName.
382 ////////////////////////////////////////////////////////////////////
383 TypedWritable *InternalName::
384 make_texcoord_from_bam(const FactoryParams &params) {
385  DatagramIterator scan;
386  BamReader *manager;
387  parse_params(params, scan, manager);
388 
389  string name = scan.get_string();
390  PT(InternalName) me;
391  if (name == "default") {
392  me = get_texcoord();
393  } else {
394  me = get_texcoord_name(name);
395  }
396 
397  me->ref();
398  manager->register_finalize(me);
399 
400  return me.p();
401 }
402 
403 ////////////////////////////////////////////////////////////////////
404 // Function: InternalName::write_datagram
405 // Access: Public
406 // Description: Function to write the important information in
407 // the particular object to a Datagram
408 ////////////////////////////////////////////////////////////////////
409 void InternalName::
410 write_datagram(BamWriter *manager, Datagram &me) {
411  me.add_string(get_name());
412 }
413 
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn&#39;t completely bogus.
void add_string(const string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:351
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
const string & get_name() const
Returns the name of the PreparedGraphicsObjects structure.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
string get_string()
Extracts a variable-length string.
virtual bool unref() const
Explicitly decrements the reference count.
Similar to MutexHolder, but for a light mutex.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:880
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:45
int get_ref_count() const
Returns the current reference count.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43