string_buffer.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2010 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. // Author: [email protected] (Jonathan Tang)
  16. #include "string_buffer.h"
  17. #include <assert.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <strings.h>
  21. #include "string_piece.h"
  22. #include "util.h"
  23. struct GumboInternalParser;
  24. static const size_t kDefaultStringBufferSize = 10;
  25. static void maybe_resize_string_buffer(
  26. struct GumboInternalParser* parser, size_t additional_chars,
  27. GumboStringBuffer* buffer) {
  28. size_t new_length = buffer->length + additional_chars;
  29. size_t new_capacity = buffer->capacity;
  30. while (new_capacity < new_length) {
  31. new_capacity *= 2;
  32. }
  33. if (new_capacity != buffer->capacity) {
  34. char* new_data = gumbo_parser_allocate(parser, new_capacity);
  35. memcpy(new_data, buffer->data, buffer->length);
  36. gumbo_parser_deallocate(parser, buffer->data);
  37. buffer->data = new_data;
  38. buffer->capacity = new_capacity;
  39. }
  40. }
  41. void gumbo_string_buffer_init(
  42. struct GumboInternalParser* parser, GumboStringBuffer* output) {
  43. output->data = gumbo_parser_allocate(parser, kDefaultStringBufferSize);
  44. output->length = 0;
  45. output->capacity = kDefaultStringBufferSize;
  46. }
  47. void gumbo_string_buffer_reserve(
  48. struct GumboInternalParser* parser, size_t min_capacity,
  49. GumboStringBuffer* output) {
  50. maybe_resize_string_buffer(parser, min_capacity - output->length, output);
  51. }
  52. void gumbo_string_buffer_append_codepoint(
  53. struct GumboInternalParser* parser, int c, GumboStringBuffer* output) {
  54. // num_bytes is actually the number of continuation bytes, 1 less than the
  55. // total number of bytes. This is done to keep the loop below simple and
  56. // should probably change if we unroll it.
  57. int num_bytes, prefix;
  58. if (c <= 0x7f) {
  59. num_bytes = 0;
  60. prefix = 0;
  61. } else if (c <= 0x7ff) {
  62. num_bytes = 1;
  63. prefix = 0xc0;
  64. } else if (c <= 0xffff) {
  65. num_bytes = 2;
  66. prefix = 0xe0;
  67. } else {
  68. num_bytes = 3;
  69. prefix = 0xf0;
  70. }
  71. maybe_resize_string_buffer(parser, num_bytes + 1, output);
  72. output->data[output->length++] = prefix | (c >> (num_bytes * 6));
  73. for (int i = num_bytes - 1; i >= 0; --i) {
  74. output->data[output->length++] = 0x80 | (0x3f & (c >> (i * 6)));
  75. }
  76. }
  77. void gumbo_string_buffer_append_string(
  78. struct GumboInternalParser* parser, GumboStringPiece* str,
  79. GumboStringBuffer* output) {
  80. maybe_resize_string_buffer(parser, str->length, output);
  81. memcpy(output->data + output->length, str->data, str->length);
  82. output->length += str->length;
  83. }
  84. char* gumbo_string_buffer_to_string(
  85. struct GumboInternalParser* parser, GumboStringBuffer* input) {
  86. char* buffer = gumbo_parser_allocate(parser, input->length + 1);
  87. memcpy(buffer, input->data, input->length);
  88. buffer[input->length] = '\0';
  89. return buffer;
  90. }
  91. void gumbo_string_buffer_destroy(
  92. struct GumboInternalParser* parser, GumboStringBuffer* buffer) {
  93. gumbo_parser_deallocate(parser, buffer->data);
  94. }