Skip to content

Commit 488d39b

Browse files
committed
add 2d and 3d array
1 parent 09233e3 commit 488d39b

File tree

1 file changed

+331
-0
lines changed

1 file changed

+331
-0
lines changed

src/psram_unique_ptr.hpp

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,3 +1388,334 @@ template <typename... Args>
13881388
inline void free_fields(Args&... fields) {
13891389
(free_field(fields), ...);
13901390
}
1391+
1392+
1393+
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
1394+
// 📌📌📌 2 D A R R A Y 📌📌📌
1395+
//
1396+
// 2D Array in PSRAM with Bounds-Check, log_e and reset()
1397+
//
1398+
// Beispielaufruf:
1399+
// ps_array2d<int32_t> s_samples; // Standardkonstruktor
1400+
// s_samples.alloc(2, 1152); // Speicher allozieren für [2][1152]
1401+
//
1402+
// int ch = 0; // Beispiel: Kanal 0
1403+
//
1404+
// // Deklaration von pcm1 als Zeiger auf das erste Element der Zeile (ähnlich wie bei samples[ch])
1405+
// int32_t* pcm1;
1406+
//
1407+
// // Zuweisung:
1408+
// pcm1 = s_samples.get_raw_row_ptr(ch);
1409+
//
1410+
// // Du kannst jetzt 'pcm1' verwenden, als wäre es ein int32_t-Array der Größe 1152
1411+
// pcm1[0] = 42;
1412+
// pcm1[1151] = 99;
1413+
//
1414+
// s_samples.reset(); // Speicher manuell freigeben
1415+
//
1416+
1417+
template <typename T>
1418+
class ps_array2d
1419+
{
1420+
public:
1421+
// Standardkonstruktor: Initialisiert die Dimensionen auf 0.
1422+
ps_array2d() : m_dim1(0), m_dim2(0) {}
1423+
1424+
// Ursprünglicher Konstruktor: Alloziert Speicher direkt bei der Erstellung.
1425+
ps_array2d(size_t dim1, size_t dim2)
1426+
: m_dim1(dim1), m_dim2(dim2)
1427+
{
1428+
alloc_internal(dim1, dim2);
1429+
}
1430+
1431+
// Neue alloc-Methode: Ermöglicht die spätere Allokation des Speichers.
1432+
bool alloc(size_t dim1, size_t dim2) {
1433+
reset();
1434+
m_dim1 = dim1;
1435+
m_dim2 = dim2;
1436+
return alloc_internal(dim1, dim2);
1437+
}
1438+
1439+
// Überladung für `alloc` ohne Dimensionen, wenn die Dimensionen bereits gesetzt sind
1440+
bool alloc() {
1441+
if (m_dim1 == 0 || m_dim2 == 0) {
1442+
log_e("ps_array2d::alloc() called without dimensions or dimensions are zero.");
1443+
return false;
1444+
}
1445+
reset();
1446+
return alloc_internal(m_dim1, m_dim2);
1447+
}
1448+
1449+
// Klammer-Operator für den Zugriff auf einzelne Elemente (Bounds-Check inklusive)
1450+
T &operator()(size_t i, size_t j)
1451+
{
1452+
if (!m_data.valid()) {
1453+
log_e("ps_array2d: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1454+
return m_dummy;
1455+
}
1456+
if (i >= m_dim1 || j >= m_dim2) {
1457+
log_e("ps_array2d out-of-bounds: (%u,%u) but dims=(%u,%u) [line %d]",
1458+
(unsigned)i, (unsigned)j, (unsigned)m_dim1, (unsigned)m_dim2, __LINE__);
1459+
return m_dummy;
1460+
}
1461+
return m_data[i * m_dim2 + j];
1462+
}
1463+
1464+
const T &operator()(size_t i, size_t j) const
1465+
{
1466+
if (!m_data.valid()) {
1467+
log_e("ps_array2d: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1468+
return m_dummy;
1469+
}
1470+
if (i >= m_dim1 || j >= m_dim2) {
1471+
log_e("ps_array2d out-of-bounds: (%u,%u) but dims=(%u,%u) [line %d]",
1472+
(unsigned)i, (unsigned)j, (unsigned)m_dim1, (unsigned)m_dim2, __LINE__);
1473+
return m_dummy;
1474+
}
1475+
return m_data[i * m_dim2 + j];
1476+
}
1477+
1478+
// NEUE METHODE: Gibt einen rohen Zeiger (T*) auf den Beginn einer spezifischen Zeile (row_index) zurück.
1479+
// Dies ist ideal für deinen Fall 'pcm1 = samples[ch];'
1480+
T* get_raw_row_ptr(size_t row_index) {
1481+
if (!m_data.valid()) {
1482+
log_e("ps_array2d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1483+
return nullptr;
1484+
}
1485+
if (row_index >= m_dim1) {
1486+
log_e("ps_array2d::get_raw_row_ptr: row_index %u out-of-bounds (%u). [line %d]",
1487+
(unsigned)row_index, (unsigned)m_dim1, __LINE__);
1488+
return nullptr;
1489+
}
1490+
return m_data.get() + row_index * m_dim2;
1491+
}
1492+
1493+
const T* get_raw_row_ptr(size_t row_index) const {
1494+
if (!m_data.valid()) {
1495+
log_e("ps_array2d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1496+
return nullptr;
1497+
}
1498+
if (row_index >= m_dim1) {
1499+
log_e("ps_array2d::get_raw_row_ptr: row_index %u out-of-bounds (%u). [line %d]",
1500+
(unsigned)row_index, (unsigned)m_dim1, __LINE__);
1501+
return nullptr;
1502+
}
1503+
return m_data.get() + row_index * m_dim2;
1504+
}
1505+
1506+
// Gibt true zurück, wenn der Speicher erfolgreich alloziiert wurde
1507+
bool is_allocated() const { return m_data.valid(); }
1508+
1509+
size_t dim1() const { return m_dim1; }
1510+
size_t dim2() const { return m_dim2; }
1511+
1512+
// Manuelle Freigabe des Speichers
1513+
void reset() {
1514+
m_data.reset();
1515+
m_dim1 = 0;
1516+
m_dim2 = 0;
1517+
}
1518+
1519+
private:
1520+
size_t m_dim1, m_dim2;
1521+
ps_ptr<T> m_data; // Verwaltet den linearen Speicherblock
1522+
static inline T m_dummy{}; // statischer Dummy-Wert
1523+
1524+
// Private Hilfsmethode für die eigentliche Allokationslogik
1525+
bool alloc_internal(size_t dim1, size_t dim2) {
1526+
if (dim1 == 0 || dim2 == 0) {
1527+
log_e("ps_array2d: Cannot allocate with zero dimensions. [line %d]", __LINE__);
1528+
return false;
1529+
}
1530+
size_t total_elements = dim1 * dim2;
1531+
m_data.calloc(total_elements, "ps_array2d_data");
1532+
if (!m_data.valid()) {
1533+
log_e("ps_array2d: Memory allocation failed for %u elements. [line %d]", (unsigned)total_elements, __LINE__);
1534+
m_dim1 = 0; m_dim2 = 0;
1535+
return false;
1536+
}
1537+
return true;
1538+
}
1539+
};
1540+
1541+
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
1542+
// psram_unique_ptr.hpp (Auszug mit ps_array3d)
1543+
//
1544+
// 📌📌📌 3 D A R R A Y 📌📌📌
1545+
//
1546+
// 3D Array in PSRAM with Bounds-Check, log_e and reset()
1547+
//
1548+
// Beispielaufruf:
1549+
// ps_array3d<int32_t> s_sbsample;
1550+
// s_sbsample.alloc(2, 36, 32);
1551+
//
1552+
// int ch = 0; // Beispiel für die erste Dimension
1553+
// int gr = 0; // Beispiel für den Gruppen-Index
1554+
//
1555+
// // Deklaration des C-Stil-Zeigers auf ein 1D-Array [32]
1556+
// int32_t (*sample)[32];
1557+
//
1558+
// // Zuweisung mithilfe der neuen Methode get_raw_row_ptr und dem passenden reinterpret_cast
1559+
// sample = reinterpret_cast<int32_t(*)[32]>(s_sbsample.get_raw_row_ptr(ch, 18 * gr));
1560+
//
1561+
// // Jetzt kannst du 'sample' verwenden:
1562+
// (*sample)[0] = 10;
1563+
//
1564+
// s_sbsample.reset();
1565+
//
1566+
1567+
1568+
template <typename T>
1569+
class ps_array3d{
1570+
public:
1571+
// Standardkonstruktor
1572+
ps_array3d() : m_dim1(0), m_dim2(0), m_dim3(0) {}
1573+
1574+
// Ursprünglicher Konstruktor
1575+
ps_array3d(size_t dim1, size_t dim2, size_t dim3)
1576+
: m_dim1(dim1), m_dim2(dim2), m_dim3(dim3)
1577+
{
1578+
alloc_internal(dim1, dim2, dim3);
1579+
}
1580+
1581+
// alloc-Methode
1582+
bool alloc(size_t dim1, size_t dim2, size_t dim3) {
1583+
reset();
1584+
m_dim1 = dim1;
1585+
m_dim2 = dim2;
1586+
m_dim3 = dim3;
1587+
return alloc_internal(dim1, dim2, dim3);
1588+
}
1589+
1590+
// Überladung für `alloc` ohne Dimensionen
1591+
bool alloc() {
1592+
if (m_dim1 == 0 || m_dim2 == 0 || m_dim3 == 0) {
1593+
log_e("ps_array3d::alloc() called without dimensions or dimensions are zero.");
1594+
return false;
1595+
}
1596+
reset();
1597+
return alloc_internal(m_dim1, m_dim2, m_dim3);
1598+
}
1599+
1600+
// Klammer-Operator für den Zugriff auf einzelne Elemente
1601+
T &operator()(size_t i, size_t j, size_t k)
1602+
{
1603+
if (!m_data.valid()) {
1604+
log_e("ps_array3d: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1605+
return m_dummy;
1606+
}
1607+
if (i >= m_dim1 || j >= m_dim2 || k >= m_dim3) {
1608+
log_e("ps_array3d out-of-bounds: (%u,%u,%u) but dims=(%u,%u,%u) [line %d]",
1609+
(unsigned)i, (unsigned)j, (unsigned)k,
1610+
(unsigned)m_dim1, (unsigned)m_dim2, (unsigned)m_dim3, __LINE__);
1611+
return m_dummy;
1612+
}
1613+
return m_data[i * (m_dim2 * m_dim3) + j * m_dim3 + k];
1614+
}
1615+
1616+
const T &operator()(size_t i, size_t j, size_t k) const
1617+
{
1618+
if (!m_data.valid()) {
1619+
log_e("ps_array3d: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1620+
return m_dummy;
1621+
}
1622+
if (i >= m_dim1 || j >= m_dim2 || k >= m_dim3) {
1623+
log_e("ps_array3d out-of-bounds: (%u,%u,%u) but dims=(%u,%u,%u) [line %d]",
1624+
(unsigned)i, (unsigned)j, (unsigned)k,
1625+
(unsigned)m_dim1, (unsigned)m_dim2, (unsigned)m_dim3, __LINE__);
1626+
return m_dummy;
1627+
}
1628+
return m_data[i * (m_dim2 * m_dim3) + j * m_dim3 + k];
1629+
}
1630+
1631+
// Methode zum Abrufen eines rohen Zeigers auf den Beginn eines 2D-Slices.
1632+
T* get_raw_slice_ptr(size_t i) {
1633+
if (!m_data.valid()) {
1634+
log_e("ps_array3d::get_raw_slice_ptr: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1635+
return nullptr;
1636+
}
1637+
if (i >= m_dim1) {
1638+
log_e("ps_array3d::get_raw_slice_ptr: dim1 index %u out-of-bounds (%u). [line %d]", (unsigned)i, (unsigned)m_dim1, __LINE__);
1639+
return nullptr;
1640+
}
1641+
return m_data.get() + i * (m_dim2 * m_dim3);
1642+
}
1643+
1644+
const T* get_raw_slice_ptr(size_t i) const {
1645+
if (!m_data.valid()) {
1646+
log_e("ps_array3d::get_raw_slice_ptr: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1647+
return nullptr;
1648+
}
1649+
if (i >= m_dim1) {
1650+
log_e("ps_array3d::get_raw_slice_ptr: dim1 index %u out-of-bounds (%u). [line %d]", (unsigned)i, (unsigned)m_dim1, __LINE__);
1651+
return nullptr;
1652+
}
1653+
return m_data.get() + i * (m_dim2 * m_dim3);
1654+
}
1655+
1656+
// NEUE METHODE: Gibt einen rohen Zeiger (T*) auf den Beginn einer spezifischen Zeile (dim2_idx)
1657+
// innerhalb eines spezifischen Slices (dim1_idx) zurück.
1658+
T* get_raw_row_ptr(size_t dim1_idx, size_t dim2_idx) {
1659+
if (!m_data.valid()) {
1660+
log_e("ps_array3d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1661+
return nullptr;
1662+
}
1663+
if (dim1_idx >= m_dim1 || dim2_idx >= m_dim2) {
1664+
log_e("ps_array3d::get_raw_row_ptr: Indices (%u,%u) out-of-bounds for dims=(%u,%u) [line %d]",
1665+
(unsigned)dim1_idx, (unsigned)dim2_idx, (unsigned)m_dim1, (unsigned)m_dim2, __LINE__);
1666+
return nullptr;
1667+
}
1668+
// Berechne den Offset für die spezifische Zeile im linearen Speicher
1669+
return m_data.get() + (dim1_idx * (m_dim2 * m_dim3)) + (dim2_idx * m_dim3);
1670+
}
1671+
1672+
const T* get_raw_row_ptr(size_t dim1_idx, size_t dim2_idx) const {
1673+
if (!m_data.valid()) {
1674+
log_e("ps_array3d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]", __LINE__);
1675+
return nullptr;
1676+
}
1677+
if (dim1_idx >= m_dim1 || dim2_idx >= m_dim2) {
1678+
log_e("ps_array3d::get_raw_row_ptr: Indices (%u,%u) out-of-bounds for dims=(%u,%u) [line %d]",
1679+
(unsigned)dim1_idx, (unsigned)dim2_idx, (unsigned)m_dim1, (unsigned)m_dim2, __LINE__);
1680+
return nullptr;
1681+
}
1682+
return m_data.get() + (dim1_idx * (m_dim2 * m_dim3)) + (dim2_idx * m_dim3);
1683+
}
1684+
1685+
1686+
// Gibt true zurück, wenn der Speicher erfolgreich alloziiert wurde
1687+
bool is_allocated() const { return m_data.valid(); }
1688+
1689+
size_t dim1() const { return m_dim1; }
1690+
size_t dim2() const { return m_dim2; }
1691+
size_t dim3() const { return m_dim3; }
1692+
1693+
// Manuelle Freigabe des Speichers
1694+
void reset() {
1695+
m_data.reset();
1696+
m_dim1 = 0;
1697+
m_dim2 = 0;
1698+
m_dim3 = 0;
1699+
}
1700+
1701+
private:
1702+
size_t m_dim1, m_dim2, m_dim3;
1703+
ps_ptr<T> m_data; // Verwaltet den linearen Speicherblock
1704+
static inline T m_dummy{}; // Dummy-Wert für Fehlerfälle
1705+
1706+
// Private Hilfsmethode für die eigentliche Allokationslogik
1707+
bool alloc_internal(size_t dim1, size_t dim2, size_t dim3) {
1708+
if (dim1 == 0 || dim2 == 0 || dim3 == 0) {
1709+
log_e("ps_array3d: Cannot allocate with zero dimensions. [line %d]", __LINE__);
1710+
return false;
1711+
}
1712+
size_t total_elements = dim1 * dim2 * dim3;
1713+
m_data.calloc(total_elements, "ps_array3d_data");
1714+
if (!m_data.valid()) {
1715+
log_e("ps_array3d: Memory allocation failed for %u elements. [line %d]", (unsigned)total_elements, __LINE__);
1716+
m_dim1 = 0; m_dim2 = 0; m_dim3 = 0;
1717+
return false;
1718+
}
1719+
return true;
1720+
}
1721+
};

0 commit comments

Comments
 (0)