1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Merge pull request #69119 from lawnjelly/faster_variant_parser_master

Add readahead to VariantParser [4.x]
This commit is contained in:
Rémi Verschelde
2022-12-05 00:06:14 +01:00
2 changed files with 80 additions and 25 deletions

View File

@@ -35,37 +35,76 @@
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/string/string_buffer.h" #include "core/string/string_buffer.h"
char32_t VariantParser::StreamFile::get_char() { char32_t VariantParser::Stream::get_char() {
return f->get_8(); // is within buffer?
if (readahead_pointer < readahead_filled) {
return readahead_buffer[readahead_pointer++];
}
// attempt to readahead
readahead_filled = _read_buffer(readahead_buffer, READAHEAD_SIZE);
if (readahead_filled) {
readahead_pointer = 0;
} else {
// EOF
readahead_pointer = 1;
eof = true;
return 0;
}
return get_char();
} }
bool VariantParser::StreamFile::is_utf8() const { bool VariantParser::StreamFile::is_utf8() const {
return true; return true;
} }
bool VariantParser::StreamFile::is_eof() const { uint32_t VariantParser::StreamFile::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) {
return f->eof_reached(); // The buffer is assumed to include at least one character (for null terminator)
} ERR_FAIL_COND_V(!p_num_chars, 0);
char32_t VariantParser::StreamString::get_char() { uint8_t *temp = (uint8_t *)alloca(p_num_chars);
if (pos > s.length()) { uint64_t num_read = f->get_buffer(temp, p_num_chars);
return 0; ERR_FAIL_COND_V(num_read == UINT64_MAX, 0);
} else if (pos == s.length()) {
// You need to try to read again when you have reached the end for EOF to be reported, // translate to wchar
// so this works the same as files (like StreamFile does) for (uint32_t n = 0; n < num_read; n++) {
pos++; p_buffer[n] = temp[n];
return 0;
} else {
return s[pos++];
} }
// could be less than p_num_chars, or zero
return num_read;
} }
bool VariantParser::StreamString::is_utf8() const { bool VariantParser::StreamString::is_utf8() const {
return false; return false;
} }
bool VariantParser::StreamString::is_eof() const { uint32_t VariantParser::StreamString::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) {
return pos > s.length(); // The buffer is assumed to include at least one character (for null terminator)
ERR_FAIL_COND_V(!p_num_chars, 0);
int available = MAX(s.length() - pos, 0);
if (available >= (int)p_num_chars) {
const char32_t *src = s.ptr();
src += pos;
memcpy(p_buffer, src, p_num_chars * sizeof(char32_t));
pos += p_num_chars;
return p_num_chars;
}
// going to reach EOF
if (available) {
const char32_t *src = s.ptr();
src += pos;
memcpy(p_buffer, src, available * sizeof(char32_t));
pos += available;
}
// add a zero
p_buffer[available] = 0;
return available;
} }
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -38,34 +38,50 @@
class VariantParser { class VariantParser {
public: public:
struct Stream { struct Stream {
virtual char32_t get_char() = 0; private:
virtual bool is_utf8() const = 0; enum { READAHEAD_SIZE = 2048 };
virtual bool is_eof() const = 0; char32_t readahead_buffer[READAHEAD_SIZE];
uint32_t readahead_pointer = 0;
uint32_t readahead_filled = 0;
bool eof = false;
protected:
virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) = 0;
public:
char32_t saved = 0; char32_t saved = 0;
char32_t get_char();
virtual bool is_utf8() const = 0;
bool is_eof() const { return eof; }
Stream() {} Stream() {}
virtual ~Stream() {} virtual ~Stream() {}
}; };
struct StreamFile : public Stream { struct StreamFile : public Stream {
protected:
virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override;
public:
Ref<FileAccess> f; Ref<FileAccess> f;
virtual char32_t get_char() override;
virtual bool is_utf8() const override; virtual bool is_utf8() const override;
virtual bool is_eof() const override;
StreamFile() {} StreamFile() {}
}; };
struct StreamString : public Stream { struct StreamString : public Stream {
String s; String s;
private:
int pos = 0; int pos = 0;
virtual char32_t get_char() override; protected:
virtual bool is_utf8() const override; virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override;
virtual bool is_eof() const override;
public:
virtual bool is_utf8() const override;
StreamString() {} StreamString() {}
}; };