1 //===-- Value.cpp -----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/Value.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/DataExtractor.h"
17 #include "lldb/Core/DataBufferHeap.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/Stream.h"
20 #include "lldb/Symbol/ClangASTType.h"
21 #include "lldb/Symbol/ClangASTContext.h"
22 #include "lldb/Symbol/ObjectFile.h"
23 #include "lldb/Symbol/SymbolContext.h"
24 #include "lldb/Symbol/Type.h"
25 #include "lldb/Symbol/Variable.h"
26 #include "lldb/Target/ExecutionContext.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/Target.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 Value::Value() :
34     m_value(),
35     m_value_type(eValueTypeScalar),
36     m_context(NULL),
37     m_context_type(eContextTypeInvalid)
38 {
39 }
40 
41 Value::Value(const Scalar& scalar) :
42     m_value(scalar),
43     m_value_type(eValueTypeScalar),
44     m_context(NULL),
45     m_context_type(eContextTypeInvalid)
46 {
47 }
48 
49 Value::Value(int v) :
50     m_value(v),
51     m_value_type(eValueTypeScalar),
52     m_context(NULL),
53     m_context_type(eContextTypeInvalid)
54 {
55 }
56 
57 Value::Value(unsigned int v) :
58     m_value(v),
59     m_value_type(eValueTypeScalar),
60     m_context(NULL),
61     m_context_type(eContextTypeInvalid)
62 {
63 }
64 
65 Value::Value(long v) :
66     m_value(v),
67     m_value_type(eValueTypeScalar),
68     m_context(NULL),
69     m_context_type(eContextTypeInvalid)
70 {
71 }
72 
73 Value::Value(unsigned long v) :
74     m_value(v),
75     m_value_type(eValueTypeScalar),
76     m_context(NULL),
77     m_context_type(eContextTypeInvalid)
78 {
79 }
80 
81 Value::Value(long long v) :
82     m_value(v),
83     m_value_type(eValueTypeScalar),
84     m_context(NULL),
85     m_context_type(eContextTypeInvalid)
86 {
87 }
88 
89 Value::Value(unsigned long long v) :
90     m_value(v),
91     m_value_type(eValueTypeScalar),
92     m_context(NULL),
93     m_context_type(eContextTypeInvalid)
94 {
95 }
96 
97 Value::Value(float v) :
98     m_value(v),
99     m_value_type(eValueTypeScalar),
100     m_context(NULL),
101     m_context_type(eContextTypeInvalid)
102 {
103 }
104 
105 Value::Value(double v) :
106     m_value(v),
107     m_value_type(eValueTypeScalar),
108     m_context(NULL),
109     m_context_type(eContextTypeInvalid)
110 {
111 }
112 
113 Value::Value(long double v) :
114     m_value(v),
115     m_value_type(eValueTypeScalar),
116     m_context(NULL),
117     m_context_type(eContextTypeInvalid)
118 {
119 }
120 
121 Value::Value(const uint8_t *bytes, int len) :
122     m_value(),
123     m_value_type(eValueTypeHostAddress),
124     m_context(NULL),
125     m_context_type(eContextTypeInvalid)
126 {
127     m_data_buffer.CopyData(bytes, len);
128     m_value = (uintptr_t)m_data_buffer.GetBytes();
129 }
130 
131 Value::Value(const Value &v) :
132     m_value(v.m_value),
133     m_value_type(v.m_value_type),
134     m_context(v.m_context),
135     m_context_type(v.m_context_type)
136 {
137     if ((uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)v.m_data_buffer.GetBytes())
138     {
139         m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),
140                                v.m_data_buffer.GetByteSize());
141 
142         m_value = (uintptr_t)m_data_buffer.GetBytes();
143     }
144 }
145 
146 Value &
147 Value::operator=(const Value &rhs)
148 {
149     if (this != &rhs)
150     {
151         m_value = rhs.m_value;
152         m_value_type = rhs.m_value_type;
153         m_context = rhs.m_context;
154         m_context_type = rhs.m_context_type;
155         if ((uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)rhs.m_data_buffer.GetBytes())
156         {
157             m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(),
158                                    rhs.m_data_buffer.GetByteSize());
159 
160             m_value = (uintptr_t)m_data_buffer.GetBytes();
161         }
162     }
163     return *this;
164 }
165 
166 Value *
167 Value::CreateProxy()
168 {
169     if (m_context_type == eContextTypeValue)
170         return ((Value*)m_context)->CreateProxy ();
171 
172     Value *ret = new Value;
173     ret->SetContext(eContextTypeValue, this);
174     return ret;
175 }
176 
177 Value *
178 Value::GetProxyTarget()
179 {
180     if (m_context_type == eContextTypeValue)
181         return (Value*)m_context;
182     else
183         return NULL;
184 }
185 
186 void
187 Value::Dump (Stream* strm)
188 {
189     if (m_context_type == eContextTypeValue)
190     {
191         ((Value*)m_context)->Dump (strm);
192         return;
193     }
194 
195     m_value.GetValue (strm, true);
196     strm->Printf(", value_type = %s, context = %p, context_type = %s",
197                 Value::GetValueTypeAsCString(m_value_type),
198                 m_context,
199                 Value::GetContextTypeAsCString(m_context_type));
200 }
201 
202 Value::ValueType
203 Value::GetValueType() const
204 {
205     if (m_context_type == eContextTypeValue)
206         return ((Value*)m_context)->GetValueType ();
207 
208     return m_value_type;
209 }
210 
211 AddressType
212 Value::GetValueAddressType () const
213 {
214     if (m_context_type == eContextTypeValue)
215         return ((Value*)m_context)->GetValueAddressType ();
216 
217     switch (m_value_type)
218     {
219     default:
220     case eValueTypeScalar:
221         break;
222     case eValueTypeLoadAddress: return eAddressTypeLoad;
223     case eValueTypeFileAddress: return eAddressTypeFile;
224     case eValueTypeHostAddress: return eAddressTypeHost;
225     }
226     return eAddressTypeInvalid;
227 }
228 
229 
230 Value::ContextType
231 Value::GetContextType() const
232 {
233     if (m_context_type == eContextTypeValue)
234         return ((Value*)m_context)->GetContextType ();
235 
236     return m_context_type;
237 }
238 
239 void
240 Value::SetValueType (Value::ValueType value_type)
241 {
242     if (m_context_type == eContextTypeValue)
243     {
244         ((Value*)m_context)->SetValueType(value_type);
245         return;
246     }
247 
248     m_value_type = value_type;
249 }
250 
251 void
252 Value::ClearContext ()
253 {
254     if (m_context_type == eContextTypeValue)
255     {
256         ((Value*)m_context)->ClearContext();
257         return;
258     }
259 
260     m_context = NULL;
261     m_context_type = eContextTypeInvalid;
262 }
263 
264 void
265 Value::SetContext (Value::ContextType context_type, void *p)
266 {
267     if (m_context_type == eContextTypeValue)
268     {
269         ((Value*)m_context)->SetContext(context_type, p);
270         return;
271     }
272 
273     m_context_type = context_type;
274     m_context = p;
275 }
276 
277 RegisterInfo *
278 Value::GetRegisterInfo()
279 {
280     if (m_context_type == eContextTypeValue)
281         return ((Value*)m_context)->GetRegisterInfo();
282 
283     if (m_context_type == eContextTypeRegisterInfo)
284         return static_cast<RegisterInfo *> (m_context);
285     return NULL;
286 }
287 
288 Type *
289 Value::GetType()
290 {
291     if (m_context_type == eContextTypeValue)
292         return ((Value*)m_context)->GetType();
293 
294     if (m_context_type == eContextTypeLLDBType)
295         return static_cast<Type *> (m_context);
296     return NULL;
297 }
298 
299 Scalar &
300 Value::GetScalar()
301 {
302     if (m_context_type == eContextTypeValue)
303         return ((Value*)m_context)->GetScalar();
304 
305     return m_value;
306 }
307 
308 void
309 Value::ResizeData(int len)
310 {
311     if (m_context_type == eContextTypeValue)
312     {
313         ((Value*)m_context)->ResizeData(len);
314         return;
315     }
316 
317     m_value_type = eValueTypeHostAddress;
318     m_data_buffer.SetByteSize(len);
319     m_value = (uintptr_t)m_data_buffer.GetBytes();
320 }
321 
322 bool
323 Value::ValueOf(ExecutionContext *exe_ctx, clang::ASTContext *ast_context)
324 {
325     if (m_context_type == eContextTypeValue)
326         return ((Value*)m_context)->ValueOf(exe_ctx, ast_context);
327 
328     switch (m_context_type)
329     {
330     default:
331     case eContextTypeInvalid:
332     case eContextTypeClangType:          // clang::Type *
333     case eContextTypeRegisterInfo:     // RegisterInfo *
334     case eContextTypeLLDBType:             // Type *
335         break;
336 
337     case eContextTypeVariable:         // Variable *
338         ResolveValue(exe_ctx, ast_context);
339         return true;
340     }
341     return false;
342 }
343 
344 size_t
345 Value::GetValueByteSize (clang::ASTContext *ast_context, Error *error_ptr)
346 {
347     if (m_context_type == eContextTypeValue)
348         return ((Value*)m_context)->GetValueByteSize(ast_context, error_ptr);
349 
350     size_t byte_size = 0;
351 
352     switch (m_context_type)
353     {
354     default:
355     case eContextTypeInvalid:
356         // If we have no context, there is no way to know how much memory to read
357         if (error_ptr)
358             error_ptr->SetErrorString ("Invalid context type, there is no way to know how much memory to read.");
359         break;
360 
361     case eContextTypeClangType:
362         if (ast_context == NULL)
363         {
364             if (error_ptr)
365                 error_ptr->SetErrorString ("Can't determine size of opaque clang type with NULL ASTContext *.");
366         }
367         else
368         {
369             uint64_t bit_width = ClangASTType::GetClangTypeBitWidth (ast_context, m_context);
370             byte_size = (bit_width + 7 ) / 8;
371         }
372         break;
373 
374     case eContextTypeRegisterInfo:     // RegisterInfo *
375         if (GetRegisterInfo())
376             byte_size = GetRegisterInfo()->byte_size;
377         else if (error_ptr)
378                 error_ptr->SetErrorString ("Can't determine byte size with NULL RegisterInfo *.");
379 
380         break;
381 
382     case eContextTypeLLDBType:             // Type *
383         if (GetType())
384             byte_size = GetType()->GetByteSize();
385         else if (error_ptr)
386             error_ptr->SetErrorString ("Can't determine byte size with NULL Type *.");
387         break;
388 
389     case eContextTypeVariable:         // Variable *
390         if (GetVariable())
391             byte_size = GetVariable()->GetType()->GetByteSize();
392         else if (error_ptr)
393             error_ptr->SetErrorString ("Can't determine byte size with NULL Variable *.");
394         break;
395     }
396 
397     if (error_ptr)
398     {
399         if (byte_size == 0)
400         {
401             if (error_ptr->Success())
402                 error_ptr->SetErrorString("Unable to determine byte size.");
403         }
404         else
405         {
406             error_ptr->Clear();
407         }
408     }
409     return byte_size;
410 }
411 
412 clang_type_t
413 Value::GetClangType ()
414 {
415     if (m_context_type == eContextTypeValue)
416         return ((Value*)m_context)->GetClangType();
417 
418     switch (m_context_type)
419     {
420     default:
421     case eContextTypeInvalid:
422         break;
423 
424     case eContextTypeClangType:
425         return m_context;
426 
427     case eContextTypeRegisterInfo:
428         break;    // TODO: Eventually convert into a clang type?
429 
430     case eContextTypeLLDBType:
431         if (GetType())
432             return GetType()->GetClangForwardType();
433         break;
434 
435     case eContextTypeVariable:
436         if (GetVariable())
437             return GetVariable()->GetType()->GetClangForwardType();
438         break;
439     }
440 
441     return NULL;
442 }
443 
444 lldb::Format
445 Value::GetValueDefaultFormat ()
446 {
447     if (m_context_type == eContextTypeValue)
448         return ((Value*)m_context)->GetValueDefaultFormat();
449 
450     switch (m_context_type)
451     {
452     default:
453     case eContextTypeInvalid:
454         break;
455 
456     case eContextTypeClangType:
457         return ClangASTType::GetFormat (m_context);
458 
459     case eContextTypeRegisterInfo:
460         if (GetRegisterInfo())
461             return GetRegisterInfo()->format;
462         break;
463 
464     case eContextTypeLLDBType:
465         if (GetType())
466             return GetType()->GetFormat();
467         break;
468 
469     case eContextTypeVariable:
470         if (GetVariable())
471             return GetVariable()->GetType()->GetFormat();
472         break;
473 
474     }
475 
476     // Return a good default in case we can't figure anything out
477     return eFormatHex;
478 }
479 
480 bool
481 Value::GetData (DataExtractor &data)
482 {
483     switch (m_value_type)
484     {
485     default:
486         break;
487 
488     case eValueTypeScalar:
489         if (m_value.GetData (data))
490             return true;
491         break;
492 
493     case eValueTypeLoadAddress:
494     case eValueTypeFileAddress:
495     case eValueTypeHostAddress:
496         if (m_data_buffer.GetByteSize())
497         {
498             data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(), data.GetByteOrder());
499             return true;
500         }
501         break;
502     }
503 
504     return false;
505 
506 }
507 
508 Error
509 Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context, DataExtractor &data, uint32_t data_offset)
510 {
511     if (m_context_type == eContextTypeValue)
512         return ((Value*)m_context)->GetValueAsData(exe_ctx, ast_context, data, data_offset);
513 
514     data.Clear();
515 
516     Error error;
517     lldb::addr_t address = LLDB_INVALID_ADDRESS;
518     AddressType address_type = eAddressTypeFile;
519     switch (m_value_type)
520     {
521     default:
522         error.SetErrorStringWithFormat("invalid value type %i", m_value_type);
523         break;
524 
525     case eValueTypeScalar:
526         data.SetByteOrder (lldb::endian::InlHostByteOrder());
527         if (m_context_type == eContextTypeClangType && ast_context)
528         {
529             uint32_t ptr_bit_width = ClangASTType::GetClangTypeBitWidth (ast_context,
530                                                                      ClangASTContext::GetVoidPtrType(ast_context, false));
531             uint32_t ptr_byte_size = (ptr_bit_width + 7) / 8;
532             data.SetAddressByteSize (ptr_byte_size);
533         }
534         else
535             data.SetAddressByteSize(sizeof(void *));
536         if (m_value.GetData (data))
537             return error;   // Success;
538         error.SetErrorStringWithFormat("extracting data from value failed");
539         break;
540 
541     case eValueTypeLoadAddress:
542         if (exe_ctx == NULL)
543         {
544             error.SetErrorString ("can't read memory (no execution context)");
545         }
546         else if (exe_ctx->process == NULL)
547         {
548             error.SetErrorString ("can't read memory (invalid process)");
549         }
550         else
551         {
552             address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
553             address_type = eAddressTypeLoad;
554             data.SetByteOrder(exe_ctx->process->GetTarget().GetArchitecture().GetByteOrder());
555             data.SetAddressByteSize(exe_ctx->process->GetTarget().GetArchitecture().GetAddressByteSize());
556         }
557         break;
558 
559     case eValueTypeFileAddress:
560         {
561             // The only thing we can currently lock down to a module so that
562             // we can resolve a file address, is a variable.
563             Variable *variable = GetVariable();
564 
565             if (GetVariable())
566             {
567                 lldb::addr_t file_addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
568                 if (file_addr != LLDB_INVALID_ADDRESS)
569                 {
570                     SymbolContext var_sc;
571                     variable->CalculateSymbolContext(&var_sc);
572                     if (var_sc.module_sp)
573                     {
574                         ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
575                         if (objfile)
576                         {
577                             Address so_addr(file_addr, objfile->GetSectionList());
578                             address = so_addr.GetLoadAddress (exe_ctx->target);
579                             if (address != LLDB_INVALID_ADDRESS)
580                             {
581                                 address_type = eAddressTypeLoad;
582                                 data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder());
583                                 data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize());
584                             }
585                             else
586                             {
587                                 data.SetByteOrder(objfile->GetByteOrder());
588                                 data.SetAddressByteSize(objfile->GetAddressByteSize());
589                             }
590                         }
591                         if (address_type == eAddressTypeFile)
592                             error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString());
593                     }
594                     else
595                     {
596                         error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", file_addr, variable->GetName().AsCString(""));
597                     }
598                 }
599                 else
600                 {
601                     error.SetErrorString ("Invalid file address.");
602                 }
603             }
604             else
605             {
606                 // Can't convert a file address to anything valid without more
607                 // context (which Module it came from)
608                 error.SetErrorString ("can't read memory from file address without more context");
609             }
610         }
611         break;
612 
613     case eValueTypeHostAddress:
614         address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
615         data.SetByteOrder(lldb::endian::InlHostByteOrder());
616         data.SetAddressByteSize(sizeof(void *));
617         address_type = eAddressTypeHost;
618         break;
619     }
620 
621     // Bail if we encountered any errors
622     if (error.Fail())
623         return error;
624 
625     if (address == LLDB_INVALID_ADDRESS)
626     {
627         error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
628         return error;
629     }
630 
631     // If we got here, we need to read the value from memory
632     uint32_t byte_size = GetValueByteSize (ast_context, &error);
633 
634     // Bail if we encountered any errors getting the byte size
635     if (error.Fail())
636         return error;
637 
638     // Make sure we have enough room within "data", and if we don't make
639     // something large enough that does
640     if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
641     {
642         DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
643         data.SetData(data_sp);
644     }
645 
646     uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
647     if (dst != NULL)
648     {
649         if (address_type == eAddressTypeHost)
650         {
651             // The address is an address in this process, so just copy it
652             memcpy (dst, (uint8_t*)NULL + address, byte_size);
653         }
654         else if (address_type == eAddressTypeLoad)
655         {
656             if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size)
657             {
658                 if (error.Success())
659                     error.SetErrorStringWithFormat("read %u bytes of memory from 0x%llx failed", (uint64_t)address, byte_size);
660                 else
661                     error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address);
662             }
663         }
664         else
665         {
666             error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
667         }
668     }
669     else
670     {
671         error.SetErrorStringWithFormat ("out of memory");
672     }
673 
674     return error;
675 }
676 
677 Scalar &
678 Value::ResolveValue(ExecutionContext *exe_ctx, clang::ASTContext *ast_context)
679 {
680     Scalar scalar;
681     if (m_context_type == eContextTypeValue)
682     {
683         // Resolve the proxy
684 
685         Value * rhs = (Value*)m_context;
686 
687         m_value = rhs->m_value;
688         m_value_type = rhs->m_value_type;
689         m_context = rhs->m_context;
690         m_context_type = rhs->m_context_type;
691 
692         if ((uintptr_t)rhs->m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)rhs->m_data_buffer.GetBytes())
693         {
694             m_data_buffer.CopyData(rhs->m_data_buffer.GetBytes(),
695                                    rhs->m_data_buffer.GetByteSize());
696 
697             m_value = (uintptr_t)m_data_buffer.GetBytes();
698         }
699     }
700 
701     if (m_context_type == eContextTypeClangType)
702     {
703         void *opaque_clang_qual_type = GetClangType();
704         switch (m_value_type)
705         {
706         case eValueTypeScalar:               // raw scalar value
707             break;
708 
709         default:
710         case eValueTypeFileAddress:
711             m_value.Clear();
712             break;
713 
714         case eValueTypeLoadAddress:          // load address value
715         case eValueTypeHostAddress:          // host address value (for memory in the process that is using liblldb)
716             {
717                 AddressType address_type = m_value_type == eValueTypeLoadAddress ? eAddressTypeLoad : eAddressTypeHost;
718                 lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
719                 DataExtractor data;
720                 if (ClangASTType::ReadFromMemory (ast_context, opaque_clang_qual_type, exe_ctx, addr, address_type, data))
721                 {
722                     if (ClangASTType::GetValueAsScalar (ast_context, opaque_clang_qual_type, data, 0, data.GetByteSize(), scalar))
723                     {
724                         m_value = scalar;
725                         m_value_type = eValueTypeScalar;
726                     }
727                     else
728                     {
729                         if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes())
730                         {
731                             m_value.Clear();
732                             m_value_type = eValueTypeScalar;
733                         }
734                     }
735                 }
736                 else
737                 {
738                     if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes())
739                     {
740                         m_value.Clear();
741                         m_value_type = eValueTypeScalar;
742                     }
743                 }
744             }
745             break;
746         }
747 
748 
749     }
750     return m_value;
751 }
752 
753 Variable *
754 Value::GetVariable()
755 {
756     if (m_context_type == eContextTypeValue)
757         return ((Value*)m_context)->GetVariable();
758 
759     if (m_context_type == eContextTypeVariable)
760         return static_cast<Variable *> (m_context);
761     return NULL;
762 }
763 
764 
765 
766 const char *
767 Value::GetValueTypeAsCString (ValueType value_type)
768 {
769     switch (value_type)
770     {
771     case eValueTypeScalar:      return "scalar";
772     case eValueTypeFileAddress: return "file address";
773     case eValueTypeLoadAddress: return "load address";
774     case eValueTypeHostAddress: return "host address";
775     };
776     return "???";
777 }
778 
779 const char *
780 Value::GetContextTypeAsCString (ContextType context_type)
781 {
782     switch (context_type)
783     {
784     case eContextTypeInvalid:               return "invalid";
785     case eContextTypeClangType:   return "clang::Type *";
786     case eContextTypeRegisterInfo:        return "RegisterInfo *";
787     case eContextTypeLLDBType:                return "Type *";
788     case eContextTypeVariable:            return "Variable *";
789     case eContextTypeValue:                 return "Value"; // TODO: Sean, more description here?
790     };
791     return "???";
792 }
793 
794 ValueList::ValueList (const ValueList &rhs)
795 {
796     m_values = rhs.m_values;
797 }
798 
799 const ValueList &
800 ValueList::operator= (const ValueList &rhs)
801 {
802     m_values = rhs.m_values;
803     return *this;
804 }
805 
806 void
807 ValueList::PushValue (const Value &value)
808 {
809     m_values.push_back (value);
810 }
811 
812 size_t
813 ValueList::GetSize()
814 {
815     return m_values.size();
816 }
817 
818 Value *
819 ValueList::GetValueAtIndex (size_t idx)
820 {
821     if (idx < GetSize())
822     {
823         return &(m_values[idx]);
824     }
825     else
826         return NULL;
827 }
828 
829 void
830 ValueList::Clear ()
831 {
832     m_values.clear();
833 }
834