diff --git a/.travis.yml b/.travis.yml index 1ed42ad..98f7a6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,21 +2,10 @@ language: node_js sudo: false -node_js: - - "node" - -compiler: clang-3.6 +node_js: node env: - - CXX=clang-3.6 - -addons: - apt: - sources: - - llvm-toolchain-precise-3.6 - - ubuntu-toolchain-r-test - packages: - - clang-3.6 + - CXX=clang branches: only: diff --git a/src/scanner.cc b/src/scanner.cc index 196153e..99f1b71 100644 --- a/src/scanner.cc +++ b/src/scanner.cc @@ -26,14 +26,18 @@ struct Scanner { Scanner() {} unsigned serialize(char *buffer) { - unsigned i = 0; - unsigned n = tags.size(); - std::memcpy(buffer, &n, sizeof(n)); - i += sizeof(n); - for (unsigned j = 0; j < n; j++) { - Tag &tag = tags[j]; + uint16_t tag_count = tags.size() > UINT16_MAX ? UINT16_MAX : tags.size(); + uint16_t serialized_tag_count = 0; + + unsigned i = sizeof(tag_count); + std::memcpy(&buffer[i], &tag_count, sizeof(tag_count)); + i += sizeof(tag_count); + + for (; serialized_tag_count < tag_count; serialized_tag_count++) { + Tag &tag = tags[serialized_tag_count]; if (tag.type == CUSTOM) { unsigned name_length = tag.custom_tag_name.size(); + if (name_length > UINT8_MAX) name_length = UINT8_MAX; if (i + 2 + name_length >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) break; buffer[i++] = static_cast(tag.type); buffer[i++] = name_length; @@ -44,6 +48,8 @@ struct Scanner { buffer[i++] = static_cast(tag.type); } } + + std::memcpy(&buffer[0], &serialized_tag_count, sizeof(serialized_tag_count)); return i; } @@ -51,15 +57,20 @@ struct Scanner { tags.clear(); if (length > 0) { unsigned i = 0; - unsigned n; - std::memcpy(&n, buffer, sizeof(n)); - i += sizeof(n); - tags.resize(n); - for (unsigned j = 0; j < n; j++) { + uint16_t tag_count, serialized_tag_count; + + std::memcpy(&serialized_tag_count, &buffer[i], sizeof(serialized_tag_count)); + i += sizeof(serialized_tag_count); + + std::memcpy(&tag_count, &buffer[i], sizeof(tag_count)); + i += sizeof(tag_count); + + tags.resize(tag_count); + for (unsigned j = 0; j < serialized_tag_count; j++) { Tag &tag = tags[j]; tag.type = static_cast(buffer[i++]); if (tag.type == CUSTOM) { - unsigned name_length = buffer[i++]; + uint16_t name_length = (uint16_t)buffer[i++]; tag.custom_tag_name.assign(&buffer[i], &buffer[i + name_length]); i += name_length; } @@ -202,8 +213,10 @@ struct Scanner { lexer->advance(lexer, false); if (lexer->lookahead == '>') { lexer->advance(lexer, false); - tags.pop_back(); - lexer->result_symbol = SELF_CLOSING_TAG_DELIMITER; + if (!tags.empty()) { + tags.pop_back(); + lexer->result_symbol = SELF_CLOSING_TAG_DELIMITER; + } return true; } return false; diff --git a/src/tag.h b/src/tag.h index da9420c..22d1e93 100644 --- a/src/tag.h +++ b/src/tag.h @@ -310,7 +310,13 @@ struct Tag { TagType type; string custom_tag_name; - Tag() : type(DIV) {} + // This default constructor is used in the case where there is not enough space + // in the serialization buffer to store all of the tags. In that case, tags + // that cannot be serialized will be treated as having an unknown type. These + // tags will be closed via implicit end tags regardless of the next closing + // tag is encountered. + Tag() : type(END_OF_VOID_TAGS) {} + Tag(TagType type, const string &name) : type(type), custom_tag_name(name) {} bool operator==(const Tag &other) const {