Skip to content

Commit

Permalink
std: add internal buffer for dynamic memory allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Jan 28, 2024
1 parent 66c5324 commit cf9535c
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 174 deletions.
4 changes: 4 additions & 0 deletions std/internal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# The `internal` standard library

The `std::internal` standard library is contains internal functionalities for standard library packages. \
Usage is restricted for all references except standard library package (standard library module).
47 changes: 47 additions & 0 deletions std/internal/dynar/dynar.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2023-2024 The Jule Programming Language.
// Use of this source code is governed by a BSD 3-Clause
// license that can be found in the LICENSE file.

#ifndef __JULE_STD_INTERNAL_DYNAR
#define __JULE_STD_INTERNAL_DYNAR

#include <new>

#include "../../../api/error.hpp"
#include "../../../api/types.hpp"
#include "../../../api/panic.hpp"

namespace jule_std
{
template <typename Item>
struct DynarBuffer
{
Item *heap = nullptr;
jule::Int len = 0;
jule::Int cap = 0;

DynarBuffer<Item>(void) = default;

DynarBuffer<Item>(const jule_std::DynarBuffer<Item> &ref)
{
this->operator=(ref);
}

void operator=(const jule_std::DynarBuffer<Item> &ref)
{
// Assignment to itself.
if (this->heap != nullptr && this->heap == ref.heap)
return;

this->heap = new (std::nothrow) Item[ref.len];
if (!this->heap)
jule::panic(__JULE_ERROR__MEMORY_ALLOCATION_FAILED);
this->len = ref.len;
this->cap = this->len;
std::copy(ref.heap, ref.heap + this->len, this->heap);
}
};

} // namespace jule_std

#endif // __JULE_STD_INTERNAL_DYNAR
120 changes: 120 additions & 0 deletions std/internal/dynar/dynar.jule
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2024 The Jule Programming Language.
// Use of this source code is governed by a BSD 3-Clause
// license that can be found in the LICENSE file.

use integ for std::jule::integrated

cpp use "dynar.hpp"

#typedef
#namespace "jule_std"
cpp struct DynarBuffer[T] {
pub heap: *T
pub len: int
pub cap: int
}

#namespace "std"
cpp unsafe fn copy(mut start: *unsafe, mut end: *unsafe, mut dest: *unsafe)

unsafe fn copy[T](mut dest: *T, mut buff: *T, len: int) {
cpp.copy(buff, buff + len, dest);
}

// Dynamic allocation on heap, suitable for dynamic array scenarios.
// Independent from slice type of Jule, pure pointer implementation.
// Implements dispose method that deallocates buffer.
// Implements internal copy algorithm that copies all elements to
// destination Dynar[T] instead of using shared memory.
//
// This structure can accept as fully unsafe.
// But all functions can use in safe Jule without Unsaf Jule.
// However, this functions have not any safet checks for performance purposes.
// Use this structure carefully.
pub struct Dynar[T] {
pub buff: cpp.DynarBuffer[T]
}

impl Dynar {
pub static fn new(): Dynar[T] {
ret Dynar[T]{}
}

// Deallocate heap.
pub fn dispose(mut self) {
self.buff.len = 0
self.buff.cap = 0
unsafe {
integ::delete_array[T](self.buff.heap)
}
self.buff.heap = nil
}

// Resizes heap. It will allocate new allocation by size and
// copies old elements into new heap after allocation, then
// deallocates old heap allocation.
// Reports whether process completed successfuly.
pub fn resize(mut self, n: int): bool {
let mut new_heap = integ::new_array[T](n)
if new_heap == nil {
ret false
}
if self.buff.heap == nil {
self.buff.heap = new_heap
self.buff.cap = n
ret true
}
unsafe {
if self.buff.len > 0 {
copy[T](new_heap, self.buff.heap, self.buff.len)
}
unsafe {
integ::delete_array[T](self.buff.heap)
}
self.buff.heap = new_heap
}
self.buff.cap = n
ret true
}

// Returns pointer that points to first element of buffer.
pub fn begin(mut self): *T {
ret self.buff.heap
}

// Returns pointer that points to end of the last element of buffer.
pub fn end(mut self): *T {
ret self.buff.heap + self.buff.len
}

// Shift elements to right by n until reach i.
// Starts at end of buffer, goes to left step by step.
pub fn shift_right(mut self, i: int, n: int) {
let mut j = self.end() - 1
let k = self.begin() + i
for j >= k; j-- {
unsafe {
*(j + n) = *j
}
}
}

// Shift elements to left by n untin reach j, start at i.
pub fn shift_left(mut self, i: int, j: int, n: int) {
let mut k = self.begin() + i
let l = self.begin() + j
for k < l; k++ {
unsafe {
*(k - n) = *k
}
}
}

// Set buffer elements, starts at i.
// Uses p for read data, reads n elements and assigns to buffer.
pub fn set(mut self, i: int, mut p: *T, n: int) {
unsafe {
copy[T](self.begin() + i, p, n)
}
}
}
40 changes: 0 additions & 40 deletions std/vec/vec.hpp

This file was deleted.

Loading

0 comments on commit cf9535c

Please sign in to comment.