xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 18426935ac8596a42f5cf1a39c7d29e97af8fe21)
1 //===-- PythonDataObjects.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 #ifdef LLDB_DISABLE_PYTHON
11 
12 // Python is disabled in this build
13 
14 #else
15 
16 #include "lldb-python.h"
17 #include "PythonDataObjects.h"
18 #include "ScriptInterpreterPython.h"
19 
20 #include "lldb/Core/Stream.h"
21 #include "lldb/Host/File.h"
22 #include "lldb/Interpreter/ScriptInterpreter.h"
23 
24 #include <stdio.h>
25 
26 using namespace lldb_private;
27 using namespace lldb;
28 
29 void
30 StructuredPythonObject::Dump(Stream &s) const
31 {
32     s << "Python Obj: 0x" << GetValue();
33 }
34 
35 //----------------------------------------------------------------------
36 // PythonObject
37 //----------------------------------------------------------------------
38 
39 void
40 PythonObject::Dump(Stream &strm) const
41 {
42     if (m_py_obj)
43     {
44         FILE *file = ::tmpfile();
45         if (file)
46         {
47             ::PyObject_Print (m_py_obj, file, 0);
48             const long length = ftell (file);
49             if (length)
50             {
51                 ::rewind(file);
52                 std::vector<char> file_contents (length,'\0');
53                 const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
54                 if (length_read > 0)
55                     strm.Write (file_contents.data(), length_read);
56             }
57             ::fclose (file);
58         }
59     }
60     else
61         strm.PutCString ("NULL");
62 }
63 
64 PyObjectType
65 PythonObject::GetObjectType() const
66 {
67     if (!IsAllocated())
68         return PyObjectType::None;
69 
70     if (PythonList::Check(m_py_obj))
71         return PyObjectType::List;
72     if (PythonDictionary::Check(m_py_obj))
73         return PyObjectType::Dictionary;
74     if (PythonString::Check(m_py_obj))
75         return PyObjectType::String;
76     if (PythonInteger::Check(m_py_obj))
77         return PyObjectType::Integer;
78     return PyObjectType::Unknown;
79 }
80 
81 PythonString
82 PythonObject::Repr()
83 {
84     if (!m_py_obj)
85         return PythonString();
86     PyObject *repr = PyObject_Repr(m_py_obj);
87     if (!repr)
88         return PythonString();
89     return PythonString(PyRefType::Owned, repr);
90 }
91 
92 PythonString
93 PythonObject::Str()
94 {
95     if (!m_py_obj)
96         return PythonString();
97     PyObject *str = PyObject_Str(m_py_obj);
98     if (!str)
99         return PythonString();
100     return PythonString(PyRefType::Owned, str);
101 }
102 
103 bool
104 PythonObject::IsNone() const
105 {
106     return m_py_obj == Py_None;
107 }
108 
109 bool
110 PythonObject::IsValid() const
111 {
112     return m_py_obj != nullptr;
113 }
114 
115 bool
116 PythonObject::IsAllocated() const
117 {
118     return IsValid() && !IsNone();
119 }
120 
121 StructuredData::ObjectSP
122 PythonObject::CreateStructuredObject() const
123 {
124     switch (GetObjectType())
125     {
126         case PyObjectType::Dictionary:
127             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
128         case PyObjectType::Integer:
129             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
130         case PyObjectType::List:
131             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
132         case PyObjectType::String:
133             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
134         case PyObjectType::None:
135             return StructuredData::ObjectSP();
136         default:
137             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
138     }
139 }
140 
141 //----------------------------------------------------------------------
142 // PythonString
143 //----------------------------------------------------------------------
144 
145 PythonString::PythonString(PyRefType type, PyObject *py_obj)
146     : PythonObject()
147 {
148     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
149 }
150 
151 PythonString::PythonString(const PythonString &object)
152     : PythonObject(object)
153 {
154 }
155 
156 PythonString::PythonString(llvm::StringRef string)
157     : PythonObject()
158 {
159     SetString(string);
160 }
161 
162 PythonString::PythonString(const char *string)
163     : PythonObject()
164 {
165     SetString(llvm::StringRef(string));
166 }
167 
168 PythonString::PythonString()
169     : PythonObject()
170 {
171 }
172 
173 PythonString::~PythonString ()
174 {
175 }
176 
177 bool
178 PythonString::Check(PyObject *py_obj)
179 {
180     if (!py_obj)
181         return false;
182 
183 #if PY_MAJOR_VERSION >= 3
184     return PyUnicode_Check(py_obj);
185 #else
186     return PyString_Check(py_obj);
187 #endif
188 }
189 
190 void
191 PythonString::Reset(PyRefType type, PyObject *py_obj)
192 {
193     // Grab the desired reference type so that if we end up rejecting
194     // `py_obj` it still gets decremented if necessary.
195     PythonObject result(type, py_obj);
196 
197     if (!PythonString::Check(py_obj))
198     {
199         PythonObject::Reset();
200         return;
201     }
202 
203     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
204     // back into the virtual implementation.
205     PythonObject::Reset(PyRefType::Borrowed, result.get());
206 }
207 
208 llvm::StringRef
209 PythonString::GetString() const
210 {
211     if (!IsValid())
212         return llvm::StringRef();
213 
214     Py_ssize_t size;
215     char *c;
216 
217 #if PY_MAJOR_VERSION >= 3
218     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
219 #else
220     PyString_AsStringAndSize(m_py_obj, &c, &size);
221 #endif
222     return llvm::StringRef(c, size);
223 }
224 
225 size_t
226 PythonString::GetSize() const
227 {
228     if (IsValid())
229     {
230 #if PY_MAJOR_VERSION >= 3
231         return PyUnicode_GetSize(m_py_obj);
232 #else
233         return PyString_Size(m_py_obj);
234 #endif
235     }
236     return 0;
237 }
238 
239 void
240 PythonString::SetString (llvm::StringRef string)
241 {
242 #if PY_MAJOR_VERSION >= 3
243     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
244     PythonObject::Reset(PyRefType::Owned, unicode);
245 #else
246     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
247     PythonObject::Reset(PyRefType::Owned, str);
248 #endif
249 }
250 
251 StructuredData::StringSP
252 PythonString::CreateStructuredString() const
253 {
254     StructuredData::StringSP result(new StructuredData::String);
255     result->SetValue(GetString());
256     return result;
257 }
258 
259 //----------------------------------------------------------------------
260 // PythonInteger
261 //----------------------------------------------------------------------
262 
263 PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
264     : PythonObject()
265 {
266     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
267 }
268 
269 PythonInteger::PythonInteger(const PythonInteger &object)
270     : PythonObject(object)
271 {
272 }
273 
274 PythonInteger::PythonInteger(int64_t value)
275     : PythonObject()
276 {
277     SetInteger(value);
278 }
279 
280 
281 PythonInteger::~PythonInteger ()
282 {
283 }
284 
285 bool
286 PythonInteger::Check(PyObject *py_obj)
287 {
288     if (!py_obj)
289         return false;
290 
291 #if PY_MAJOR_VERSION >= 3
292     // Python 3 does not have PyInt_Check.  There is only one type of
293     // integral value, long.
294     return PyLong_Check(py_obj);
295 #else
296     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
297 #endif
298 }
299 
300 void
301 PythonInteger::Reset(PyRefType type, PyObject *py_obj)
302 {
303     // Grab the desired reference type so that if we end up rejecting
304     // `py_obj` it still gets decremented if necessary.
305     PythonObject result(type, py_obj);
306 
307     if (!PythonInteger::Check(py_obj))
308     {
309         PythonObject::Reset();
310         return;
311     }
312 
313 #if PY_MAJOR_VERSION < 3
314     // Always store this as a PyLong, which makes interoperability between
315     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
316     // since 3.x doesn't even have a PyInt.
317     if (PyInt_Check(py_obj))
318     {
319         // Since we converted the original object to a different type, the new
320         // object is an owned object regardless of the ownership semantics requested
321         // by the user.
322         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
323     }
324 #endif
325 
326     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
327 
328     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
329     // back into the virtual implementation.
330     PythonObject::Reset(PyRefType::Borrowed, result.get());
331 }
332 
333 int64_t
334 PythonInteger::GetInteger() const
335 {
336     if (m_py_obj)
337     {
338         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
339 
340         return PyLong_AsLongLong(m_py_obj);
341     }
342     return UINT64_MAX;
343 }
344 
345 void
346 PythonInteger::SetInteger(int64_t value)
347 {
348     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
349 }
350 
351 StructuredData::IntegerSP
352 PythonInteger::CreateStructuredInteger() const
353 {
354     StructuredData::IntegerSP result(new StructuredData::Integer);
355     result->SetValue(GetInteger());
356     return result;
357 }
358 
359 //----------------------------------------------------------------------
360 // PythonList
361 //----------------------------------------------------------------------
362 
363 PythonList::PythonList(PyInitialValue value)
364     : PythonObject()
365 {
366     if (value == PyInitialValue::Empty)
367         Reset(PyRefType::Owned, PyList_New(0));
368 }
369 
370 PythonList::PythonList(int list_size)
371     : PythonObject()
372 {
373     Reset(PyRefType::Owned, PyList_New(list_size));
374 }
375 
376 PythonList::PythonList(PyRefType type, PyObject *py_obj)
377     : PythonObject()
378 {
379     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
380 }
381 
382 PythonList::PythonList(const PythonList &list)
383     : PythonObject(list)
384 {
385 }
386 
387 PythonList::~PythonList ()
388 {
389 }
390 
391 bool
392 PythonList::Check(PyObject *py_obj)
393 {
394     if (!py_obj)
395         return false;
396     return PyList_Check(py_obj);
397 }
398 
399 void
400 PythonList::Reset(PyRefType type, PyObject *py_obj)
401 {
402     // Grab the desired reference type so that if we end up rejecting
403     // `py_obj` it still gets decremented if necessary.
404     PythonObject result(type, py_obj);
405 
406     if (!PythonList::Check(py_obj))
407     {
408         PythonObject::Reset();
409         return;
410     }
411 
412     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
413     // back into the virtual implementation.
414     PythonObject::Reset(PyRefType::Borrowed, result.get());
415 }
416 
417 uint32_t
418 PythonList::GetSize() const
419 {
420     if (IsValid())
421         return PyList_GET_SIZE(m_py_obj);
422     return 0;
423 }
424 
425 PythonObject
426 PythonList::GetItemAtIndex(uint32_t index) const
427 {
428     if (IsValid())
429         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
430     return PythonObject();
431 }
432 
433 void
434 PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
435 {
436     if (IsAllocated() && object.IsValid())
437     {
438         // PyList_SetItem is documented to "steal" a reference, so we need to
439         // convert it to an owned reference by incrementing it.
440         Py_INCREF(object.get());
441         PyList_SetItem(m_py_obj, index, object.get());
442     }
443 }
444 
445 void
446 PythonList::AppendItem(const PythonObject &object)
447 {
448     if (IsAllocated() && object.IsValid())
449     {
450         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
451         // here like we do with `PyList_SetItem`.
452         PyList_Append(m_py_obj, object.get());
453     }
454 }
455 
456 StructuredData::ArraySP
457 PythonList::CreateStructuredArray() const
458 {
459     StructuredData::ArraySP result(new StructuredData::Array);
460     uint32_t count = GetSize();
461     for (uint32_t i = 0; i < count; ++i)
462     {
463         PythonObject obj = GetItemAtIndex(i);
464         result->AddItem(obj.CreateStructuredObject());
465     }
466     return result;
467 }
468 
469 //----------------------------------------------------------------------
470 // PythonDictionary
471 //----------------------------------------------------------------------
472 
473 PythonDictionary::PythonDictionary(PyInitialValue value)
474     : PythonObject()
475 {
476     if (value == PyInitialValue::Empty)
477         Reset(PyRefType::Owned, PyDict_New());
478 }
479 
480 PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
481     : PythonObject()
482 {
483     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
484 }
485 
486 PythonDictionary::PythonDictionary(const PythonDictionary &object)
487     : PythonObject(object)
488 {
489 }
490 
491 PythonDictionary::~PythonDictionary ()
492 {
493 }
494 
495 bool
496 PythonDictionary::Check(PyObject *py_obj)
497 {
498     if (!py_obj)
499         return false;
500 
501     return PyDict_Check(py_obj);
502 }
503 
504 void
505 PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
506 {
507     // Grab the desired reference type so that if we end up rejecting
508     // `py_obj` it still gets decremented if necessary.
509     PythonObject result(type, py_obj);
510 
511     if (!PythonDictionary::Check(py_obj))
512     {
513         PythonObject::Reset();
514         return;
515     }
516 
517     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
518     // back into the virtual implementation.
519     PythonObject::Reset(PyRefType::Borrowed, result.get());
520 }
521 
522 uint32_t
523 PythonDictionary::GetSize() const
524 {
525     if (IsValid())
526         return PyDict_Size(m_py_obj);
527     return 0;
528 }
529 
530 PythonList
531 PythonDictionary::GetKeys() const
532 {
533     if (IsValid())
534         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
535     return PythonList(PyInitialValue::Invalid);
536 }
537 
538 PythonObject
539 PythonDictionary::GetItemForKey(const PythonObject &key) const
540 {
541     if (IsAllocated() && key.IsValid())
542         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
543     return PythonObject();
544 }
545 
546 void
547 PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
548 {
549     if (IsAllocated() && key.IsValid() && value.IsValid())
550         PyDict_SetItem(m_py_obj, key.get(), value.get());
551 }
552 
553 StructuredData::DictionarySP
554 PythonDictionary::CreateStructuredDictionary() const
555 {
556     StructuredData::DictionarySP result(new StructuredData::Dictionary);
557     PythonList keys(GetKeys());
558     uint32_t num_keys = keys.GetSize();
559     for (uint32_t i = 0; i < num_keys; ++i)
560     {
561         PythonObject key = keys.GetItemAtIndex(i);
562         PythonObject value = GetItemForKey(key);
563         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
564         result->AddItem(key.Str().GetString(), structured_value);
565     }
566     return result;
567 }
568 
569 #endif
570