History

Implement seek() utfbytes() in Sys module. - Updated tests for utfbytes() - Updated utf8 API surface to support the general length case (codepoint _and_ byte) - Testing of seek() still outstanding Comment added regarding stack frame pointer in stack frames.

arr committed 9 years ago

Commit a6da1dc1 parent 1af55286 files · +94 −18Browse files

Showing the changes to src/vm/sys/Sysmod.cpp (1 of 6 files). Show all

Unified · Split

src/vm/sys/Sysmod.cpp+57−4
@@ -188,6 +188,15 @@ namespace · 187 unmodified lines
188188 throw vm_user_exception{ "Write operation error" };
189189 }
190190
191+ big_t seek(const std::ios::seekdir start, const big_t offset)
192+ {
193+ if (_stream == nullptr)
194+ throw vm_user_exception{ "Unable to seek on a fifo file descriptor (e.g. stdin, stdout, stderr)" };
195+
196+ auto new_offset = _stream->rdbuf()->pubseekoff(static_cast<std::streamoff>(offset), start, _fd_mode);
197+ return static_cast<big_t>(new_offset);
198+ }
199+
191200 private:
192201 const word_t _fd_mode;
193202 vm_string_t *_fd_path;
@@ -218,6 +227,21 @@ namespace · 24 unmodified lines
218227
219228 return om;
220229 }
230+
231+ std::ios::seekdir convert_to_seekdir(const word_t start)
232+ {
233+ switch (start)
234+ {
235+ case Sys_SEEKSTART:
236+ return std::ios::beg;
237+ case Sys_SEEKRELA:
238+ return std::ios::cur;
239+ case Sys_SEEKEND:
240+ return std::ios::end;
241+ default:
242+ throw vm_user_exception{ "Invalid seek mode" };
243+ }
244+ }
221245 }
222246
223247 void
@@ -612,7 +636,6 @@ Sys_read(vm_registers_t &r, vm_t &vm) · 388 unmodified lines
612636 auto &fp = r.stack.peek_frame()->base<F_Sys_read>();
613637
614638 const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf);
615− assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);
616639
617640 auto n = fp.n;
618641 if (buffer == nullptr || n <= 0)
@@ -621,11 +644,16 @@ Sys_read(vm_registers_t &r, vm_t &vm) · 2 unmodified lines
621644 return;
622645 }
623646
647+ assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);
648+
624649 // [SPEC] Supplying a size greater than the buffer length is
625650 // equivalent to indicating the entire buffer should be filled.
626651 n = std::min(n, buffer->get_length());
627652
628653 auto fd_alloc = vm_alloc_t::from_allocation(fp.fd);
654+ if (fd_alloc == nullptr)
655+ throw dereference_nil{ "Read from file descriptor" };
656+
629657 assert(fd_alloc->alloc_type == T_FD);
630658
631659 auto fd = fd_alloc->get_allocation<vm_fd_t>();
@@ -650,7 +678,16 @@ void · 18 unmodified lines
650678 Sys_seek(vm_registers_t &r, vm_t &vm)
651679 {
652680 auto &fp = r.stack.peek_frame()->base<F_Sys_seek>();
653− throw vm_system_exception{ "Instruction not implemented" };
681+
682+ auto fd_alloc = vm_alloc_t::from_allocation(fp.fd);
683+ if (fd_alloc == nullptr)
684+ throw dereference_nil{ "Seek in file descriptor" };
685+
686+ assert(fd_alloc->alloc_type == T_FD);
687+ auto fd = fd_alloc->get_allocation<vm_fd_t>();
688+
689+ const auto start = convert_to_seekdir(fp.start);
690+ *fp.ret = fd->seek(start, fp.off);
654691 }
655692
656693 void
@@ -814,7 +851,19 @@ void · 157 unmodified lines
814851 Sys_utfbytes(vm_registers_t &r, vm_t &vm)
815852 {
816853 auto &fp = r.stack.peek_frame()->base<F_Sys_utfbytes>();
817− throw vm_system_exception{ "Instruction not implemented" };
854+ const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf);
855+
856+ const auto n = fp.n;
857+ if (buffer == nullptr || n > buffer->get_length())
858+ throw out_of_range_memory{};
859+
860+ assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);
861+
862+ auto raw_buffer = reinterpret_cast<uint8_t *>(buffer->at(0));
863+
864+ const auto len = utf8::count_codepoints(raw_buffer, n);
865+ *fp.ret = static_cast<word_t>(len.byte_count);
866+ assert(*fp.ret <= n && "Code points should not exceed number of bytes processed");
818867 }
819868
820869 void
@@ -830,7 +879,6 @@ Sys_write(vm_registers_t &r, vm_t &vm) · 9 unmodified lines
830879 auto &fp = r.stack.peek_frame()->base<F_Sys_write>();
831880
832881 const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf);
833− assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);
834882
835883 auto n = fp.n;
836884 if (buffer == nullptr || n <= 0)
@@ -839,11 +887,16 @@ Sys_write(vm_registers_t &r, vm_t &vm) · 2 unmodified lines
839887 return;
840888 }
841889
890+ assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);
891+
842892 // [SPEC] Supplying a size greater than the buffer length is
843893 // equivalent to indicating the entire buffer should be written.
844894 n = std::min(n, buffer->get_length());
845895
846896 auto fd_alloc = vm_alloc_t::from_allocation(fp.fd);
897+ if (fd_alloc == nullptr)
898+ throw dereference_nil{ "Write to file descriptor" };
899+
847900 assert(fd_alloc->alloc_type == T_FD);
848901
849902 auto fd = fd_alloc->get_allocation<vm_fd_t>();