//MemCopy void MemInterface::commandMemCopy(void) { int32_t length = cb->popValue().getInt(); int32_t dest = cb->popValue().getInt(); int32_t destId = cb->popValue().getInt(); uint8_t *destmem = getMemblock(destId); if (destmem == 0) return; int32_t src = cb->popValue().getInt(); int32_t srcId = cb->popValue().getInt(); uint8_t *srcmem = getMemblock(srcId); if (srcmem == 0) return; #ifdef CBE_MEMBLOCK_BOUNDS_CHECK int32_t destMemSize = *(int32_t*)destmem; int32_t srcMemSize = *(int32_t*)srcmem; if ((dest + length > destMemSize) || (src + length > srcMemSize)) { cb->errors->createError("MemCopy out of bounds", "Destination index: " + boost::lexical_cast<string>(dest) + "\n Source index: " + boost::lexical_cast<string>(src) + "\n Trying to copy " + boost::lexical_cast<string>(length) + " bytes"); return; } #endif memcpy(destmem + dest + 4, srcmem + src + 4, length); }
word_t _dup(CrocThread* t) { auto mb = checkMemblockParam(t, 0); croc_memblock_new(t, mb->data.length); getMemblock(Thread::from(t), -1)->data.slicea(mb->data); return 1; }
//DeleteMEMBlock void MemInterface::commandDeleteMEMBlock(void) { int32_t id = cb->popValue().getInt(); uint8_t* mem = getMemblock(id); if (mem == 0) return; delete mem; }
//MemblockSize void MemInterface::functionMEMBlockSize(void){ int32_t id = cb->popValue().getInt(); int32_t *mem = (int32_t *)getMemblock(id); if (mem == 0) return; cb->pushValue(*mem); }
//PeekFloat void MemInterface::functionPeekFloat(void){ int32_t position = cb->popValue().getInt(); int32_t id = cb->popValue().getInt(); uint8_t *mem = getMemblock(id); if (mem == 0) return; MEMBLOCK_BOUNDS_CHECK(mem, "PeekFloat", position, 4); cb->pushValue(*(float*)(&mem[position + 4])); }
//PokeByte void MemInterface::commandPokeByte(void) { uint8_t value = cb->popValue().toByte(); int32_t position = cb->popValue().getInt(); int32_t id = cb->popValue().getInt(); uint8_t * mem = getMemblock(id); if (mem == 0) return; MEMBLOCK_BOUNDS_CHECK(mem, "PokeByte", position, 1); *((uint8_t *)(mem + position + 4)) = value; }
word_t _opCatAssign(CrocThread* t) { auto mb = checkMemblockParam(t, 0); auto data = mb->data; if(!mb->ownData) croc_eh_throwStd(t, "ValueError", "Attempting to append to a memblock which does not own its data"); croc_ex_checkAnyParam(t, 1); auto numParams = croc_getStackSize(t) - 1; uint64_t totalLen = data.length; for(uword i = 1; i <= numParams; i++) totalLen += checkMemblockParam(t, i)->data.length; if(totalLen > std::numeric_limits<uword>::max()) croc_eh_throwStd(t, "RangeError", "Invalid size (%" CROC_UINTEGER_FORMAT ")", totalLen); auto oldLen = data.length; auto t_ = Thread::from(t); mb->resize(t_->vm->mem, cast(uword)totalLen); uword j = oldLen; for(uword i = 1; i <= numParams; i++) { if(croc_is(t, 0, i)) { // special case for when we're appending a memblock to itself; use the old length memcpy(&data[j], data.ptr, oldLen); j += oldLen; } else { auto other = getMemblock(t_, i)->data; memcpy(&data[j], other.ptr, other.length); j += other.length; } } return 0; }
//ResizeMEMblock void MemInterface::commandResizeMEMBlock(void) { int32_t size = cb->popValue().getInt(); int32_t id = cb->popValue().getInt(); assert(id); uint8_t *mem = getMemblock(id); if (mem == 0) return; int32_t oldsize = mem[0]; uint8_t *newBlock = new uint8_t[size + 4]; *((int32_t*)newBlock) = size; if (oldsize < size) { memset(newBlock + 4 + oldsize, 0, size - oldsize); memcpy(newBlock + 4, mem + 4, (size_t)oldsize); } else { memcpy(newBlock + 4, mem + 4, (size_t)size); } delete mem; memblockMap[id] = newBlock; }