/* CrossLang is a dynamically-typed scripting language built on TessesFramework, named in honor of Jesus's sacrifice. Copyright (C) 2026 Mike Nolan SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "CrossLang.hpp" namespace Tesses::CrossLang { int64_t TObjectStream::_GetPosInternal() { return Tesses::Framework::Streams::Stream::GetLength(); } TObjectStream::TObjectStream(std::shared_ptr gc, TObject obj) { this->ls = new GCList(gc); this->ls->Add(obj); this->obj = obj; TDictionary *dict; if (GetObjectHeap(obj, dict)) { gc->BarrierBegin(); if (!dict->HasValue("Read")) { dict->DeclareFunction( gc, "Read", "Read from stream", {"buff", "off", "len"}, [](GCList &ls, std::vector args) -> TObject { return (int64_t)0; }); } if (!dict->HasValue("Write")) { dict->DeclareFunction( gc, "Write", "Write to stream", {"buff", "off", "len"}, [](GCList &ls, std::vector args) -> TObject { return (int64_t)0; }); } if (!dict->HasValue("getCanRead")) { dict->DeclareFunction( gc, "getCanRead", "Can read from stream", {}, [](GCList &ls, std::vector args) -> TObject { return false; }); } if (!dict->HasValue("getCanWrite")) { dict->DeclareFunction( gc, "getCanWrite", "Can write to stream", {}, [](GCList &ls, std::vector args) -> TObject { return false; }); } if (!dict->HasValue("getCanSeek")) { dict->DeclareFunction( gc, "getCanSeek", "Can seek in stream", {}, [](GCList &ls, std::vector args) -> TObject { return false; }); } if (!dict->HasValue("getPosition")) { dict->DeclareFunction( gc, "getPosition", "Can get position in stream", {}, [](GCList &ls, std::vector args) -> TObject { return (int64_t)0; }); } if (!dict->HasValue("getLength")) { dict->DeclareFunction( gc, "getPosition", "Can get position in stream", {}, [this](GCList &ls, std::vector args) -> TObject { return _GetPosInternal(); }); } if (!dict->HasValue("getEndOfStream")) { dict->DeclareFunction( gc, "getEndOfStream", "Is at end of stream", {}, [](GCList &ls, std::vector args) -> TObject { return false; }); } gc->BarrierEnd(); } } bool TObjectStream::EndOfStream() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { auto res = dict->CallMethod(*ls, "getEndOfStream", {}); bool r; if (GetObject(res, r)) return r; } return false; } size_t TObjectStream::Read(uint8_t *buff, size_t sz) { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { GCList ls2(this->ls->GetGC()); TByteArray *arr = TByteArray::Create(ls2); arr->data.resize(sz); auto res = dict->CallMethod(ls2, "Read", {arr, (int64_t)0L, (int64_t)sz}); memcpy(buff, arr->data.data(), std::min(sz, arr->data.size())); int64_t r; if (GetObject(res, r)) return r; } return 0; } size_t TObjectStream::Write(const uint8_t *buff, size_t sz) { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { GCList ls2(this->ls->GetGC()); TByteArray *arr = TByteArray::Create(ls2); arr->data.resize(sz); memcpy(arr->data.data(), buff, sz); auto res = dict->CallMethod(ls2, "Write", {arr, (int64_t)0L, (int64_t)sz}); int64_t r; if (GetObject(res, r)) return r; } return 0; } bool TObjectStream::CanRead() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { auto res = dict->CallMethod(*ls, "getCanRead", {}); bool r; if (GetObject(res, r)) return r; } return false; } bool TObjectStream::CanWrite() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { auto res = dict->CallMethod(*ls, "getCanWrite", {}); bool r; if (GetObject(res, r)) return r; } return false; } bool TObjectStream::CanSeek() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { auto res = dict->CallMethod(*ls, "getCanSeek", {}); bool r; if (GetObject(res, r)) return r; } return false; } int64_t TObjectStream::GetPosition() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { auto res = dict->CallMethod(*ls, "getPosition", {}); int64_t r; if (GetObject(res, r)) return r; } return 0; } int64_t TObjectStream::GetLength() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { auto res = dict->CallMethod(*ls, "getEndOfStream", {}); bool r; if (GetObject(res, r)) return r; } return Tesses::Framework::Streams::Stream::GetLength(); } void TObjectStream::Flush() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { dict->CallMethod(*ls, "Flush", {}); } } void TObjectStream::Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence) { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { dict->CallMethod( *ls, "Seek", {pos, (int64_t)(whence == Tesses::Framework::Streams::SeekOrigin::Begin ? 0 : whence == Tesses::Framework::Streams::SeekOrigin::Current ? 1 : 2)}); } } void TObjectStream::Close() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { dict->CallMethod(*ls, "Dispose", {}); } } TObjectStream::~TObjectStream() { TDictionary *dict; if (GetObjectHeap(this->obj, dict)) { dict->CallMethod(*ls, "Dispose", {}); } delete this->ls; } } // namespace Tesses::CrossLang