herb 0.7.5 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +8 -5
  3. data/config.yml +26 -6
  4. data/ext/herb/error_helpers.c +57 -3
  5. data/ext/herb/error_helpers.h +1 -1
  6. data/ext/herb/extconf.rb +1 -0
  7. data/ext/herb/extension.c +10 -24
  8. data/ext/herb/extension_helpers.c +3 -3
  9. data/ext/herb/extension_helpers.h +1 -1
  10. data/ext/herb/nodes.c +72 -37
  11. data/herb.gemspec +0 -2
  12. data/lib/herb/ast/helpers.rb +11 -0
  13. data/lib/herb/ast/node.rb +15 -6
  14. data/lib/herb/ast/nodes.rb +609 -392
  15. data/lib/herb/cli.rb +31 -0
  16. data/lib/herb/colors.rb +82 -0
  17. data/lib/herb/engine/compiler.rb +140 -14
  18. data/lib/herb/engine/debug_visitor.rb +1 -5
  19. data/lib/herb/engine/parser_error_overlay.rb +1 -1
  20. data/lib/herb/engine.rb +8 -14
  21. data/lib/herb/errors.rb +166 -56
  22. data/lib/herb/location.rb +2 -2
  23. data/lib/herb/project.rb +86 -21
  24. data/lib/herb/token.rb +14 -2
  25. data/lib/herb/version.rb +1 -1
  26. data/lib/herb.rb +1 -0
  27. data/sig/herb/ast/helpers.rbs +3 -0
  28. data/sig/herb/ast/node.rbs +12 -5
  29. data/sig/herb/ast/nodes.rbs +124 -62
  30. data/sig/herb/colors.rbs +35 -0
  31. data/sig/herb/engine/compiler.rbs +23 -1
  32. data/sig/herb/errors.rbs +74 -20
  33. data/sig/herb/token.rbs +8 -0
  34. data/sig/herb_c_extension.rbs +1 -1
  35. data/sig/serialized_ast_errors.rbs +8 -0
  36. data/src/analyze.c +420 -171
  37. data/src/analyze_helpers.c +5 -0
  38. data/src/analyze_missing_end.c +147 -0
  39. data/src/analyze_transform.c +196 -0
  40. data/src/analyzed_ruby.c +23 -2
  41. data/src/ast_node.c +5 -5
  42. data/src/ast_nodes.c +179 -179
  43. data/src/ast_pretty_print.c +232 -232
  44. data/src/element_source.c +7 -6
  45. data/src/errors.c +246 -126
  46. data/src/extract.c +92 -34
  47. data/src/herb.c +37 -49
  48. data/src/html_util.c +34 -96
  49. data/src/include/analyze.h +10 -2
  50. data/src/include/analyze_helpers.h +3 -0
  51. data/src/include/analyzed_ruby.h +4 -2
  52. data/src/include/ast_node.h +2 -2
  53. data/src/include/ast_nodes.h +67 -66
  54. data/src/include/ast_pretty_print.h +2 -2
  55. data/src/include/element_source.h +3 -1
  56. data/src/include/errors.h +30 -14
  57. data/src/include/extract.h +4 -4
  58. data/src/include/herb.h +6 -7
  59. data/src/include/html_util.h +4 -5
  60. data/src/include/lexer.h +1 -3
  61. data/src/include/lexer_peek_helpers.h +14 -14
  62. data/src/include/lexer_struct.h +3 -2
  63. data/src/include/macros.h +4 -0
  64. data/src/include/parser.h +12 -6
  65. data/src/include/parser_helpers.h +25 -15
  66. data/src/include/pretty_print.h +38 -28
  67. data/src/include/token.h +5 -8
  68. data/src/include/utf8.h +3 -2
  69. data/src/include/util/hb_arena.h +31 -0
  70. data/src/include/util/hb_arena_debug.h +8 -0
  71. data/src/include/util/hb_array.h +33 -0
  72. data/src/include/util/hb_buffer.h +34 -0
  73. data/src/include/util/hb_string.h +29 -0
  74. data/src/include/util/hb_system.h +9 -0
  75. data/src/include/util.h +3 -14
  76. data/src/include/version.h +1 -1
  77. data/src/include/visitor.h +1 -1
  78. data/src/io.c +7 -4
  79. data/src/lexer.c +61 -88
  80. data/src/lexer_peek_helpers.c +35 -37
  81. data/src/main.c +19 -23
  82. data/src/parser.c +282 -201
  83. data/src/parser_helpers.c +46 -40
  84. data/src/parser_match_tags.c +316 -0
  85. data/src/pretty_print.c +82 -106
  86. data/src/token.c +18 -65
  87. data/src/utf8.c +4 -4
  88. data/src/util/hb_arena.c +179 -0
  89. data/src/util/hb_arena_debug.c +237 -0
  90. data/src/{array.c → util/hb_array.c} +26 -27
  91. data/src/util/hb_buffer.c +203 -0
  92. data/src/util/hb_string.c +85 -0
  93. data/src/util/hb_system.c +30 -0
  94. data/src/util.c +29 -99
  95. data/src/visitor.c +54 -54
  96. data/templates/ext/herb/error_helpers.c.erb +3 -3
  97. data/templates/ext/herb/error_helpers.h.erb +1 -1
  98. data/templates/ext/herb/nodes.c.erb +11 -6
  99. data/templates/java/error_helpers.c.erb +75 -0
  100. data/templates/java/error_helpers.h.erb +20 -0
  101. data/templates/java/nodes.c.erb +97 -0
  102. data/templates/java/nodes.h.erb +23 -0
  103. data/templates/java/org/herb/ast/Errors.java.erb +121 -0
  104. data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
  105. data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
  106. data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
  107. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
  108. data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
  109. data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
  110. data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
  111. data/templates/lib/herb/ast/nodes.rb.erb +28 -16
  112. data/templates/lib/herb/errors.rb.erb +17 -12
  113. data/templates/rust/src/ast/nodes.rs.erb +220 -0
  114. data/templates/rust/src/errors.rs.erb +216 -0
  115. data/templates/rust/src/nodes.rs.erb +374 -0
  116. data/templates/src/analyze_missing_end.c.erb +36 -0
  117. data/templates/src/analyze_transform.c.erb +24 -0
  118. data/templates/src/ast_nodes.c.erb +14 -14
  119. data/templates/src/ast_pretty_print.c.erb +36 -36
  120. data/templates/src/errors.c.erb +31 -31
  121. data/templates/src/include/ast_nodes.h.erb +10 -9
  122. data/templates/src/include/ast_pretty_print.h.erb +2 -2
  123. data/templates/src/include/errors.h.erb +6 -6
  124. data/templates/src/parser_match_tags.c.erb +38 -0
  125. data/templates/src/visitor.c.erb +4 -4
  126. data/templates/template.rb +22 -3
  127. data/templates/wasm/error_helpers.cpp.erb +9 -9
  128. data/templates/wasm/error_helpers.h.erb +1 -1
  129. data/templates/wasm/nodes.cpp.erb +9 -9
  130. data/templates/wasm/nodes.h.erb +1 -1
  131. data/vendor/prism/Rakefile +4 -1
  132. data/vendor/prism/config.yml +2 -1
  133. data/vendor/prism/include/prism/ast.h +31 -1
  134. data/vendor/prism/include/prism/diagnostic.h +1 -0
  135. data/vendor/prism/include/prism/version.h +3 -3
  136. data/vendor/prism/src/diagnostic.c +3 -1
  137. data/vendor/prism/src/prism.c +130 -71
  138. data/vendor/prism/src/util/pm_string.c +6 -8
  139. data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
  140. data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
  141. data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
  142. data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
  143. data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
  144. data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
  145. metadata +34 -20
  146. data/lib/herb/libherb/array.rb +0 -51
  147. data/lib/herb/libherb/ast_node.rb +0 -50
  148. data/lib/herb/libherb/buffer.rb +0 -56
  149. data/lib/herb/libherb/extract_result.rb +0 -20
  150. data/lib/herb/libherb/lex_result.rb +0 -32
  151. data/lib/herb/libherb/libherb.rb +0 -52
  152. data/lib/herb/libherb/parse_result.rb +0 -20
  153. data/lib/herb/libherb/token.rb +0 -46
  154. data/lib/herb/libherb.rb +0 -35
  155. data/src/buffer.c +0 -241
  156. data/src/include/array.h +0 -33
  157. data/src/include/buffer.h +0 -39
  158. data/src/include/json.h +0 -28
  159. data/src/include/memory.h +0 -12
  160. data/src/json.c +0 -205
  161. data/src/memory.c +0 -53
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- require "forwardable"
7
-
8
- module Herb
9
- module LibHerb
10
- attach_function :array_get, [:pointer, :int], :pointer
11
- attach_function :array_capacity, [:pointer], :size_t
12
- attach_function :array_size, [:pointer], :size_t
13
-
14
- class Array
15
- extend Forwardable
16
-
17
- attr_reader :pointer, :item_class
18
-
19
- def_delegators :items, :first, :last, :[]
20
-
21
- def initialize(pointer, item_class)
22
- @pointer = pointer
23
- @item_class = item_class
24
- end
25
-
26
- def capacity
27
- LibHerb.array_capacity(pointer)
28
- end
29
-
30
- def size
31
- LibHerb.array_size(pointer)
32
- end
33
-
34
- def item_pointers
35
- size.times.map { |item|
36
- LibHerb.array_get(pointer, item)
37
- }
38
- end
39
-
40
- def items
41
- item_pointers.map { |item_pointer|
42
- item_class.new(item_pointer)
43
- }
44
- end
45
-
46
- def inspect
47
- %(#<#{self.class} size=#{size} capacity=#{capacity} item_class=#{item_class} pointer=#{pointer}>)
48
- end
49
- end
50
- end
51
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- module Herb
7
- module LibHerb
8
- attach_function :ast_node_type, [:pointer], :int
9
- attach_function :ast_node_type_to_string, [:pointer], :string
10
- attach_function :ast_node_children, [:pointer], :pointer
11
- attach_function :ast_node_child_count, [:pointer], :size_t
12
- attach_function :ast_pretty_print_node, [:pointer, :size_t, :size_t, :pointer], :void
13
- attach_function :ast_node_free, [:pointer], :void
14
-
15
- class ASTNode
16
- attr_reader :pointer
17
-
18
- def initialize(pointer)
19
- @pointer = pointer
20
- end
21
-
22
- def type_int
23
- LibHerb.ast_node_type(pointer)
24
- end
25
-
26
- def type
27
- LibHerb.ast_node_type_to_string(pointer)
28
- end
29
-
30
- def child_count
31
- LibHerb.ast_node_child_count(pointer)
32
- end
33
-
34
- def children
35
- LibHerb::Array.new(
36
- LibHerb.ast_node_children(pointer),
37
- ASTNode
38
- )
39
- end
40
-
41
- def inspect
42
- LibHerb::Buffer.with do |output|
43
- LibHerb.ast_pretty_print_node(pointer, 0, 0, output.pointer)
44
-
45
- output.read.force_encoding("utf-8") # TODO: remove force_encoding
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- module Herb
7
- module LibHerb
8
- attach_function :buffer_init, [:pointer], :bool
9
- attach_function :buffer_free, [:pointer], :void
10
- attach_function :buffer_value, [:pointer], :pointer
11
- attach_function :buffer_length, [:pointer], :size_t
12
- attach_function :buffer_capacity, [:pointer], :size_t
13
- attach_function :buffer_sizeof, [], :size_t
14
- attach_function :buffer_append, [:pointer, :pointer], :void
15
-
16
- class Buffer
17
- SIZEOF = LibHerb.buffer_sizeof
18
-
19
- attr_reader :pointer
20
-
21
- def initialize(pointer)
22
- @pointer = pointer
23
- end
24
-
25
- def append(string)
26
- LibHerb.buffer_append(pointer, string)
27
- end
28
-
29
- def value
30
- LibHerb.buffer_value(pointer)
31
- end
32
-
33
- def length
34
- LibHerb.buffer_length(pointer)
35
- end
36
-
37
- def capacity
38
- LibHerb.buffer_capacity(pointer)
39
- end
40
-
41
- def read
42
- value.read_string(length)
43
- end
44
-
45
- def self.with
46
- FFI::MemoryPointer.new(SIZEOF) do |pointer|
47
- raise "couldn't allocate Buffer" unless LibHerb.buffer_init(pointer)
48
-
49
- return yield new(pointer)
50
- ensure
51
- LibHerb.buffer_free(pointer)
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- require "forwardable"
7
-
8
- module Herb
9
- class ExtractResult
10
- extend Forwardable
11
-
12
- def_delegators :@buffer, :read
13
-
14
- attr_accessor :buffer
15
-
16
- def initialize(pointer)
17
- @buffer = LibHerb::Buffer.new(pointer)
18
- end
19
- end
20
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- require "forwardable"
7
-
8
- module Herb
9
- class LexResult
10
- extend Forwardable
11
-
12
- def_delegators :@array, :items, :size, :capacity
13
-
14
- attr_accessor :array
15
-
16
- def initialize(pointer)
17
- @array = LibHerb::Array.new(pointer, LibHerb::Token)
18
- end
19
-
20
- def as_json
21
- JSON.parse(to_json)
22
- end
23
-
24
- def to_json(*_args)
25
- "[#{@array.items.map(&:to_json).join(", ")}]"
26
- end
27
-
28
- def inspect
29
- @array.items.map(&:inspect).join("\n")
30
- end
31
- end
32
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- require "herb/libherb/ast_node"
7
- require "herb/libherb/buffer"
8
- require "herb/libherb/array"
9
- require "herb/libherb/token"
10
-
11
- require "herb/libherb/lex_result"
12
- require "herb/libherb/parse_result"
13
-
14
- module Herb
15
- VERSION = LibHerb.herb_version.read_string
16
-
17
- def self.parse(source)
18
- ParseResult.new(
19
- LibHerb.herb_parse(source)
20
- )
21
- end
22
-
23
- def self.lex(source)
24
- LexResult.new(
25
- LibHerb.herb_lex(source)
26
- )
27
- end
28
-
29
- def self.lex_to_json(source)
30
- LibHerb::Buffer.with do |output|
31
- LibHerb.herb_lex_json_to_buffer(source, output.pointer)
32
-
33
- JSON.parse(output.read.force_encoding("utf-8"))
34
- end
35
- end
36
-
37
- def self.extract_ruby(source)
38
- LibHerb::Buffer.with do |output|
39
- LibHerb.herb_extract_ruby_to_buffer(source, output.pointer)
40
-
41
- output.read
42
- end
43
- end
44
-
45
- def self.extract_html(source)
46
- LibHerb::Buffer.with do |output|
47
- LibHerb.herb_extract_html_to_buffer(source, output.pointer)
48
-
49
- output.read
50
- end
51
- end
52
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- require "forwardable"
7
-
8
- module Herb
9
- class ParseResult
10
- extend Forwardable
11
-
12
- def_delegators :@root_node, :type, :child_count
13
-
14
- attr_accessor :root_node
15
-
16
- def initialize(pointer)
17
- @root_node = LibHerb::ASTNode.new(pointer)
18
- end
19
- end
20
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- module Herb
7
- module LibHerb
8
- attach_function :token_to_string, [:pointer], :string
9
- attach_function :token_to_json, [:pointer], :string
10
- attach_function :token_type_to_string, [:int], :pointer
11
- attach_function :token_value, [:pointer], :pointer
12
- attach_function :token_type, [:pointer], :int
13
-
14
- class Token
15
- attr_reader :pointer
16
-
17
- def initialize(pointer)
18
- @pointer = pointer
19
- end
20
-
21
- def value
22
- @value ||= LibHerb.token_value(pointer).read_string
23
- end
24
-
25
- def type
26
- @type ||= LibHerb.token_type_to_string(type_int).read_string
27
- end
28
-
29
- def type_int
30
- @type_int ||= LibHerb.token_type(pointer)
31
- end
32
-
33
- def inspect
34
- LibHerb.token_to_string(pointer).force_encoding("utf-8")
35
- end
36
-
37
- def as_json
38
- JSON.parse(to_json)
39
- end
40
-
41
- def to_json(*_args)
42
- LibHerb.token_to_json(pointer).force_encoding("utf-8")
43
- end
44
- end
45
- end
46
- end
data/lib/herb/libherb.rb DELETED
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: ignore
3
-
4
- # rbs_inline: disabled
5
-
6
- require "ffi"
7
- require "rbconfig"
8
-
9
- module Herb
10
- module LibHerb
11
- extend FFI::Library
12
-
13
- def self.library_extension
14
- RbConfig::CONFIG["DLEXT"]
15
- end
16
-
17
- def self.library_name
18
- "libherb.#{library_extension}"
19
- end
20
-
21
- def self.library_path
22
- File.expand_path("../../#{library_name}", __dir__)
23
- end
24
-
25
- ffi_lib(library_path)
26
-
27
- attach_function :herb_lex_to_buffer, [:pointer, :pointer], :void
28
- attach_function :herb_lex_json_to_buffer, [:pointer, :pointer], :void
29
- attach_function :herb_lex, [:pointer], :pointer
30
- attach_function :herb_parse, [:pointer], :pointer
31
- attach_function :herb_extract_ruby_to_buffer, [:pointer, :pointer], :void
32
- attach_function :herb_extract_html_to_buffer, [:pointer, :pointer], :void
33
- attach_function :herb_version, [], :pointer
34
- end
35
- end
data/src/buffer.c DELETED
@@ -1,241 +0,0 @@
1
- #include <stdint.h>
2
- #include <stdio.h>
3
- #include <string.h>
4
-
5
- #include "include/buffer.h"
6
- #include "include/macros.h"
7
- #include "include/memory.h"
8
- #include "include/util.h"
9
-
10
- bool buffer_init(buffer_T* buffer) {
11
- buffer->capacity = 1024;
12
- buffer->length = 0;
13
- buffer->value = nullable_safe_malloc((buffer->capacity + 1) * sizeof(char));
14
-
15
- if (!buffer->value) {
16
- fprintf(stderr, "Error: Failed to initialize buffer with capacity of %zu.\n", buffer->capacity);
17
- return false;
18
- }
19
-
20
- buffer->value[0] = '\0';
21
-
22
- return true;
23
- }
24
-
25
- buffer_T buffer_new(void) {
26
- buffer_T buffer;
27
- buffer_init(&buffer);
28
- return buffer;
29
- }
30
-
31
- char* buffer_value(const buffer_T* buffer) {
32
- return buffer->value;
33
- }
34
-
35
- size_t buffer_length(const buffer_T* buffer) {
36
- return buffer->length;
37
- }
38
-
39
- size_t buffer_capacity(const buffer_T* buffer) {
40
- return buffer->capacity;
41
- }
42
-
43
- size_t buffer_sizeof(void) {
44
- return sizeof(buffer_T);
45
- }
46
-
47
- /**
48
- * Increases the capacity of the buffer if needed to accommodate additional content.
49
- * This function only handles memory allocation and does not modify the buffer content
50
- * or null termination.
51
- *
52
- * @param buffer The buffer to increase capacity for
53
- * @param additional_capacity The additional length needed beyond current buffer capacity
54
- * @return true if capacity was increased, false if reallocation failed
55
- */
56
- bool buffer_increase_capacity(buffer_T* buffer, const size_t additional_capacity) {
57
- if (additional_capacity + 1 >= SIZE_MAX) {
58
- fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
59
- exit(1);
60
- }
61
-
62
- const size_t new_capacity = buffer->capacity + additional_capacity;
63
-
64
- return buffer_resize(buffer, new_capacity);
65
- }
66
-
67
- /**
68
- * Resizes the capacity of the buffer to the specified new capacity.
69
- *
70
- * @param buffer The buffer to resize
71
- * @param new_capacity The new capacity to resize the buffer to
72
- * @return true if capacity was resized, false if reallocation failed
73
- */
74
- bool buffer_resize(buffer_T* buffer, const size_t new_capacity) {
75
- if (new_capacity + 1 >= SIZE_MAX) {
76
- fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
77
- exit(1);
78
- }
79
-
80
- char* new_value = nullable_safe_realloc(buffer->value, new_capacity + 1);
81
-
82
- if (unlikely(new_value == NULL)) {
83
- fprintf(stderr, "Error: Failed to resize buffer to %zu.\n", new_capacity);
84
- exit(1);
85
- }
86
-
87
- buffer->value = new_value;
88
- buffer->capacity = new_capacity;
89
-
90
- return true;
91
- }
92
-
93
- /**
94
- * Expands the capacity of the buffer by doubling its current capacity.
95
- * This function is a convenience function that calls buffer_increase_capacity
96
- * with a factor of 2.
97
- *
98
- * @param buffer The buffer to expand capacity for
99
- * @return true if capacity was increased, false if reallocation failed
100
- */
101
- bool buffer_expand_capacity(buffer_T* buffer) {
102
- return buffer_resize(buffer, buffer->capacity * 2);
103
- }
104
-
105
- /**
106
- * Expands the capacity of the buffer if needed to accommodate additional content.
107
- * This function is a convenience function that calls buffer_has_capacity and
108
- * buffer_expand_capacity.
109
- *
110
- * @param buffer The buffer to expand capacity for
111
- * @param required_length The additional length needed beyond current buffer capacity
112
- * @return true if capacity was increased, false if reallocation failed
113
- */
114
- bool buffer_expand_if_needed(buffer_T* buffer, const size_t required_length) {
115
- if (buffer_has_capacity(buffer, required_length)) { return true; }
116
-
117
- bool should_double_capacity = required_length < buffer->capacity;
118
- size_t new_capacity = 0;
119
-
120
- if (should_double_capacity) {
121
- new_capacity = buffer->capacity * 2;
122
- } else {
123
- new_capacity = buffer->capacity + (required_length * 2);
124
- }
125
-
126
- return buffer_resize(buffer, new_capacity);
127
- }
128
-
129
- /**
130
- * Appends a null-terminated string to the buffer.
131
- * @note This function requires that 'text' is a properly null-terminated string.
132
- * When reading data from files or other non-string sources, ensure the data is
133
- * null-terminated before calling this function, or use buffer_append_with_length instead.
134
- *
135
- * @param buffer The buffer to append to
136
- * @param text A null-terminated string to append
137
- * @return void
138
- */
139
- void buffer_append(buffer_T* buffer, const char* text) {
140
- if (!buffer || !text) { return; }
141
- if (text[0] == '\0') { return; }
142
-
143
- size_t text_length = strlen(text);
144
-
145
- if (!buffer_expand_if_needed(buffer, text_length)) { return; }
146
-
147
- memcpy(buffer->value + buffer->length, text, text_length);
148
- buffer->length += text_length;
149
- buffer->value[buffer->length] = '\0';
150
- }
151
-
152
- /**
153
- * Appends a string of specified length to the buffer.
154
- * Unlike buffer_append(), this function does not require the text to be
155
- * null-terminated as it uses the provided length instead of strlen().
156
- * This is particularly useful when working with data from files, network
157
- * buffers, or other non-null-terminated sources.
158
- *
159
- * @param buffer The buffer to append to
160
- * @param text The text to append (doesn't need to be null-terminated)
161
- * @param length The number of bytes to append from text
162
- * @return void
163
- */
164
- void buffer_append_with_length(buffer_T* buffer, const char* text, const size_t length) {
165
- if (!buffer || !text || length == 0) { return; }
166
- if (!buffer_expand_if_needed(buffer, length)) { return; }
167
-
168
- memcpy(buffer->value + buffer->length, text, length);
169
-
170
- buffer->length += length;
171
- buffer->value[buffer->length] = '\0';
172
- }
173
-
174
- void buffer_append_char(buffer_T* buffer, const char character) {
175
- static char string[2];
176
-
177
- string[0] = character;
178
- string[1] = '\0';
179
-
180
- buffer_append(buffer, string);
181
- }
182
-
183
- void buffer_append_repeated(buffer_T* buffer, const char character, size_t length) {
184
- if (length == 0) { return; }
185
-
186
- char* spaces = malloc(length + 1);
187
- if (!spaces) { return; }
188
-
189
- memset(spaces, character, length);
190
- spaces[length] = '\0';
191
-
192
- buffer_append(buffer, spaces);
193
-
194
- free(spaces);
195
- }
196
-
197
- void buffer_append_whitespace(buffer_T* buffer, const size_t length) {
198
- buffer_append_repeated(buffer, ' ', length);
199
- }
200
-
201
- void buffer_prepend(buffer_T* buffer, const char* text) {
202
- if (!buffer || !text) { return; }
203
- if (text[0] == '\0') { return; }
204
-
205
- size_t text_length = strlen(text);
206
-
207
- if (!buffer_expand_if_needed(buffer, text_length)) { return; }
208
-
209
- memmove(buffer->value + text_length, buffer->value, buffer->length + 1);
210
- memcpy(buffer->value, text, text_length);
211
-
212
- buffer->length += text_length;
213
- }
214
-
215
- void buffer_concat(buffer_T* destination, buffer_T* source) {
216
- if (source->length == 0) { return; }
217
- if (!buffer_expand_if_needed(destination, source->length)) { return; }
218
-
219
- memcpy(destination->value + destination->length, source->value, source->length);
220
-
221
- destination->length += source->length;
222
- destination->value[destination->length] = '\0';
223
- }
224
-
225
- bool buffer_has_capacity(buffer_T* buffer, const size_t required_length) {
226
- return (buffer->length + required_length <= buffer->capacity);
227
- }
228
-
229
- void buffer_clear(buffer_T* buffer) {
230
- buffer->length = 0;
231
- buffer->value[0] = '\0';
232
- }
233
-
234
- void buffer_free(buffer_T* buffer) {
235
- if (!buffer) { return; }
236
-
237
- if (buffer->value != NULL) { free(buffer->value); }
238
-
239
- buffer->value = NULL;
240
- buffer->length = buffer->capacity = 0;
241
- }
data/src/include/array.h DELETED
@@ -1,33 +0,0 @@
1
- #ifndef HERB_ARRAY_H
2
- #define HERB_ARRAY_H
3
-
4
- #include <stdlib.h>
5
-
6
- typedef struct ARRAY_STRUCT {
7
- void** items;
8
- size_t size;
9
- size_t capacity;
10
- } array_T;
11
-
12
- array_T* array_init(size_t capacity);
13
-
14
- void* array_get(const array_T* array, size_t index);
15
- void* array_first(array_T* array);
16
- void* array_last(array_T* array);
17
-
18
- void array_append(array_T* array, void* item);
19
- void array_set(const array_T* array, size_t index, void* item);
20
- void array_free(array_T** array);
21
- void array_remove(array_T* array, size_t index);
22
-
23
- size_t array_index_of(array_T* array, void* item);
24
- void array_remove_item(array_T* array, void* item);
25
-
26
- void array_push(array_T* array, void* item);
27
- void* array_pop(array_T* array);
28
-
29
- size_t array_capacity(const array_T* array);
30
- size_t array_size(const array_T* array);
31
- size_t array_sizeof(void);
32
-
33
- #endif
data/src/include/buffer.h DELETED
@@ -1,39 +0,0 @@
1
- #ifndef HERB_BUFFER_H
2
- #define HERB_BUFFER_H
3
-
4
- #include <stdbool.h>
5
- #include <stdlib.h>
6
-
7
- typedef struct BUFFER_STRUCT {
8
- char* value;
9
- size_t length;
10
- size_t capacity;
11
- } buffer_T;
12
-
13
- bool buffer_init(buffer_T* buffer);
14
- buffer_T buffer_new(void);
15
-
16
- bool buffer_increase_capacity(buffer_T* buffer, size_t additional_capacity);
17
- bool buffer_has_capacity(buffer_T* buffer, size_t required_length);
18
- bool buffer_expand_capacity(buffer_T* buffer);
19
- bool buffer_expand_if_needed(buffer_T* buffer, size_t required_length);
20
- bool buffer_resize(buffer_T* buffer, size_t new_capacity);
21
-
22
- void buffer_append(buffer_T* buffer, const char* text);
23
- void buffer_append_with_length(buffer_T* buffer, const char* text, size_t length);
24
- void buffer_append_char(buffer_T* buffer, char character);
25
- void buffer_append_repeated(buffer_T* buffer, char character, size_t length);
26
- void buffer_append_whitespace(buffer_T* buffer, size_t length);
27
- void buffer_prepend(buffer_T* buffer, const char* text);
28
- void buffer_concat(buffer_T* destination, buffer_T* source);
29
-
30
- char* buffer_value(const buffer_T* buffer);
31
-
32
- size_t buffer_length(const buffer_T* buffer);
33
- size_t buffer_capacity(const buffer_T* buffer);
34
- size_t buffer_sizeof(void);
35
-
36
- void buffer_clear(buffer_T* buffer);
37
- void buffer_free(buffer_T* buffer);
38
-
39
- #endif