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 (5 of 6 files). Show all

Unified · Split

5 files
  1. src/exec/main.cpp +1 −1
  2. src/include/utf8.h +9 −2
  3. src/vm/string.cpp +8 −3
  4. src/vm/sys/Sysmod.cpp +57 −4
  5. src/vm/utf8.cpp +11 −8
src/exec/main.cpp+1−1
@@ -32,7 +32,7 @@ namespace · 31 unmodified lines
3232 {
3333 word_t noret;
3434 pointer_t command_module_ref;
35− pointer_t command_stack_frame; // Should not be marked as memory managed pointer field
35+ pointer_t command_stack_frame; // [SPEC] Stack frames are not managed by the GC and as such should not be marked as a pointer field. See pointer map below.
3636 };
3737
3838 const auto entry_frame_pointer_map = std::vector<byte_t>{ 0x04 };
src/include/utf8.h+9−2
@@ -29,9 +29,16 @@ namespace disvm · 28 unmodified lines
2929 const disvm::runtime::rune_t max_supported_codepoint = max_codepoint_4_byte;
3030 };
3131
32− // Compute the number of code points in the supplied string
32+ // Lengths of a UTF-8 string
33+ struct utf8_length_t
34+ {
35+ const std::size_t codepoint_count;
36+ const std::size_t byte_count;
37+ };
38+
39+ // Compute the number of codepoints in the supplied string
3340 // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
34− std::size_t count_codepoints(const uint8_t *str, const std::size_t max_len);
41+ utf8_length_t count_codepoints(const uint8_t *str, const std::size_t max_len);
3542
3643 enum class decode_state_t
3744 {
src/vm/string.cpp+8−3
@@ -191,10 +191,15 @@ vm_string_t::vm_string_t(std::size_t encoded_str_len, const uint8_t *encoded_str · 190 unmodified lines
191191 , _mem{}
192192 {
193193 assert((encoded_str_len > 0 && encoded_str != nullptr) || (encoded_str_len == 0 && encoded_str == nullptr));
194− auto character_count = utf8::count_codepoints(encoded_str, encoded_str_len);
195− _character_size = (encoded_str_len != character_count) ? sizeof(rune_t) : sizeof(char);
194+ const auto utf8_length = utf8::count_codepoints(encoded_str, encoded_str_len);
196195
197− _length = static_cast<word_t>(character_count);
196+ // Check if the supplied string is completely valid UTF-8 - only valid UTF-8 strings can be DisVM strings.
197+ if (encoded_str_len != utf8_length.byte_count)
198+ throw invalid_utf8{};
199+
200+ _character_size = (encoded_str_len != utf8_length.codepoint_count) ? sizeof(rune_t) : sizeof(char);
201+
202+ _length = static_cast<word_t>(utf8_length.codepoint_count);
198203 _length_max = sizeof(_mem.local) / _character_size;
199204
200205 // Allocate memory based on character count and size
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>();
src/vm/utf8.cpp+11−8
@@ -54,28 +54,31 @@ utf8::decode_state_t disvm::runtime::utf8::decode_step(utf8::decode_state_t &sta · 53 unmodified lines
5454
5555 // Adopted from 'countCodePoints(uint8_t* s, size_t* count)'
5656 // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
57−std::size_t disvm::runtime::utf8::count_codepoints(const uint8_t *str, const std::size_t max_len)
57+utf8::utf8_length_t disvm::runtime::utf8::count_codepoints(const uint8_t *str, const std::size_t max_len)
5858 {
5959 if (str == nullptr)
6060 {
6161 assert(max_len == 0);
62− return std::size_t{ 0 };
62+ return{ 0, 0 };
6363 }
6464
6565 auto single_character = rune_t{};
6666 auto points = std::size_t{ 0 };
6767 auto state = utf8::decode_state_t::accept;
6868
69− for (auto i = std::size_t{ 0 }; i < max_len; ++i)
69+ auto last = str;
70+ for (auto curr = last; curr < (str + max_len); ++curr)
7071 {
71− if (utf8::decode_state_t::accept == utf8::decode_step(state, single_character, str[i]))
72+ if (utf8::decode_state_t::accept == utf8::decode_step(state, single_character, *curr))
73+ {
74+ last = curr;
7275 points++;
76+ }
7377 }
7478
75− if (state != utf8::decode_state_t::accept)
76− throw invalid_utf8{};
77−
78− return points;
79+ assert(str <= last);
80+ const auto byte_count = static_cast<std::size_t>(last - str + 1);
81+ return{ points, byte_count };
7982 }
8083
8184 std::size_t disvm::runtime::utf8::decode(const uint8_t *str, rune_t &codepoint)