2011-10-23 17:48:10 -07:00
|
|
|
#include "pyc_numeric.h"
|
|
|
|
#include "pyc_module.h"
|
2009-07-24 08:35:21 +00:00
|
|
|
#include "data.h"
|
2009-07-24 21:15:51 +00:00
|
|
|
#include <cstring>
|
2009-07-24 08:35:21 +00:00
|
|
|
|
2011-10-02 12:14:54 -07:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#define snprintf sprintf_s
|
|
|
|
#endif
|
|
|
|
|
2009-07-24 08:35:21 +00:00
|
|
|
/* PycInt */
|
|
|
|
void PycInt::load(PycData* stream, PycModule*)
|
|
|
|
{
|
|
|
|
m_value = stream->get32();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* PycLong */
|
|
|
|
void PycLong::load(PycData* stream, PycModule*)
|
|
|
|
{
|
2009-07-25 02:41:15 +00:00
|
|
|
if (type() == TYPE_INT64) {
|
2022-12-01 11:35:14 -08:00
|
|
|
m_value.reserve(4);
|
2009-07-25 02:41:15 +00:00
|
|
|
int lo = stream->get32();
|
|
|
|
int hi = stream->get32();
|
|
|
|
m_value.push_back((lo ) & 0xFFFF);
|
|
|
|
m_value.push_back((lo >> 16) & 0xFFFF);
|
|
|
|
m_value.push_back((hi ) & 0xFFFF);
|
|
|
|
m_value.push_back((hi >> 16) & 0xFFFF);
|
|
|
|
m_size = (hi & 0x80000000) != 0 ? -4 : 4;
|
|
|
|
} else {
|
|
|
|
m_size = stream->get32();
|
2011-09-23 19:57:50 -07:00
|
|
|
int actualSize = m_size >= 0 ? m_size : -m_size;
|
2022-12-01 11:35:14 -08:00
|
|
|
m_value.reserve(actualSize);
|
2009-07-25 02:41:15 +00:00
|
|
|
for (int i=0; i<actualSize; i++)
|
|
|
|
m_value.push_back(stream->get16());
|
|
|
|
}
|
2009-07-24 08:35:21 +00:00
|
|
|
}
|
|
|
|
|
2009-07-24 21:15:51 +00:00
|
|
|
bool PycLong::isEqual(PycRef<PycObject> obj) const
|
|
|
|
{
|
2017-07-05 16:36:04 -07:00
|
|
|
if (type() != obj.type())
|
2009-07-25 02:41:15 +00:00
|
|
|
return false;
|
|
|
|
|
2009-07-24 21:15:51 +00:00
|
|
|
PycRef<PycLong> longObj = obj.cast<PycLong>();
|
|
|
|
if (m_size != longObj->m_size)
|
|
|
|
return false;
|
2022-12-01 11:35:14 -08:00
|
|
|
auto it1 = m_value.cbegin();
|
|
|
|
auto it2 = longObj->m_value.cbegin();
|
|
|
|
while (it1 != m_value.cend()) {
|
2009-07-24 21:15:51 +00:00
|
|
|
if (*it1 != *it2)
|
|
|
|
return false;
|
|
|
|
++it1, ++it2;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-23 21:46:05 -07:00
|
|
|
std::string PycLong::repr() const
|
|
|
|
{
|
|
|
|
// Longs are printed as hex, since it's easier (and faster) to convert
|
|
|
|
// arbitrary-length integers to a power of two than an arbitrary base
|
|
|
|
|
|
|
|
if (m_size == 0)
|
|
|
|
return "0x0L";
|
|
|
|
|
|
|
|
// Realign to 32 bits, since Python uses only 15
|
2022-12-01 11:35:14 -08:00
|
|
|
std::vector<unsigned> bits;
|
|
|
|
bits.reserve((m_value.size() + 1) / 2);
|
2011-09-23 21:46:05 -07:00
|
|
|
int shift = 0, temp = 0;
|
2019-10-04 15:56:24 -07:00
|
|
|
for (auto bit : m_value) {
|
|
|
|
temp |= unsigned(bit & 0xFFFF) << shift;
|
2011-09-23 21:46:05 -07:00
|
|
|
shift += 15;
|
|
|
|
if (shift >= 32) {
|
|
|
|
bits.push_back(temp);
|
|
|
|
shift -= 32;
|
2019-10-04 15:56:24 -07:00
|
|
|
temp = unsigned(bit & 0xFFFF) >> (15 - shift);
|
2011-09-23 21:46:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (temp)
|
|
|
|
bits.push_back(temp);
|
|
|
|
|
|
|
|
std::string accum;
|
|
|
|
accum.resize(3 + (bits.size() * 8) + 2);
|
|
|
|
char* aptr = &accum[0];
|
|
|
|
|
|
|
|
if (m_size < 0)
|
|
|
|
*aptr++ = '-';
|
|
|
|
*aptr++ = '0';
|
|
|
|
*aptr++ = 'x';
|
|
|
|
|
2022-12-01 11:35:14 -08:00
|
|
|
auto iter = bits.crbegin();
|
2011-09-23 21:46:05 -07:00
|
|
|
aptr += snprintf(aptr, 9, "%X", *iter++);
|
|
|
|
while (iter != bits.rend())
|
|
|
|
aptr += snprintf(aptr, 9, "%08X", *iter++);
|
|
|
|
*aptr++ = 'L';
|
2018-01-28 14:33:26 -08:00
|
|
|
*aptr = 0;
|
2011-09-23 21:46:05 -07:00
|
|
|
return accum;
|
|
|
|
}
|
|
|
|
|
2009-07-24 08:35:21 +00:00
|
|
|
|
|
|
|
/* PycFloat */
|
|
|
|
void PycFloat::load(PycData* stream, PycModule*)
|
|
|
|
{
|
|
|
|
int len = stream->getByte();
|
2019-10-02 16:01:54 -07:00
|
|
|
if (len < 0)
|
|
|
|
throw std::bad_alloc();
|
|
|
|
|
|
|
|
m_value.resize(len);
|
|
|
|
if (len > 0)
|
|
|
|
stream->getBuffer(len, &m_value.front());
|
2009-07-24 08:35:21 +00:00
|
|
|
}
|
2009-07-24 21:15:51 +00:00
|
|
|
|
|
|
|
bool PycFloat::isEqual(PycRef<PycObject> obj) const
|
|
|
|
{
|
2017-07-05 16:36:04 -07:00
|
|
|
if (type() != obj.type())
|
2009-07-25 02:41:15 +00:00
|
|
|
return false;
|
|
|
|
|
2009-07-24 21:15:51 +00:00
|
|
|
PycRef<PycFloat> floatObj = obj.cast<PycFloat>();
|
2019-10-02 16:01:54 -07:00
|
|
|
return m_value == floatObj->m_value;
|
2009-07-24 21:15:51 +00:00
|
|
|
}
|
2009-07-25 02:41:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* PycComplex */
|
|
|
|
void PycComplex::load(PycData* stream, PycModule* mod)
|
|
|
|
{
|
|
|
|
PycFloat::load(stream, mod);
|
|
|
|
|
|
|
|
int len = stream->getByte();
|
2019-10-02 16:01:54 -07:00
|
|
|
if (len < 0)
|
|
|
|
throw std::bad_alloc();
|
|
|
|
|
|
|
|
m_imag.resize(len);
|
|
|
|
if (len > 0)
|
|
|
|
stream->getBuffer(len, &m_imag.front());
|
2009-07-25 02:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool PycComplex::isEqual(PycRef<PycObject> obj) const
|
|
|
|
{
|
|
|
|
if (!PycFloat::isEqual(obj))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PycRef<PycComplex> floatObj = obj.cast<PycComplex>();
|
2019-10-02 16:01:54 -07:00
|
|
|
return m_imag == floatObj->m_imag;
|
2009-07-25 02:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* PycCFloat */
|
|
|
|
void PycCFloat::load(PycData* stream, PycModule*)
|
|
|
|
{
|
2017-07-05 15:53:35 -07:00
|
|
|
Pyc_INT64 bits = stream->get64();
|
|
|
|
memcpy(&m_value, &bits, sizeof(bits));
|
2009-07-25 02:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* PycCComplex */
|
|
|
|
void PycCComplex::load(PycData* stream, PycModule* mod)
|
|
|
|
{
|
|
|
|
PycCFloat::load(stream, mod);
|
2017-07-05 15:53:35 -07:00
|
|
|
Pyc_INT64 bits = stream->get64();
|
|
|
|
memcpy(&m_imag, &bits, sizeof(bits));
|
2009-07-25 02:41:15 +00:00
|
|
|
}
|