qiita_marker 0.23.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +50 -0
- data/Rakefile +113 -0
- data/bin/qiita_marker +123 -0
- data/ext/qiita_marker/arena.c +103 -0
- data/ext/qiita_marker/autolink.c +425 -0
- data/ext/qiita_marker/autolink.h +8 -0
- data/ext/qiita_marker/blocks.c +1596 -0
- data/ext/qiita_marker/buffer.c +278 -0
- data/ext/qiita_marker/buffer.h +116 -0
- data/ext/qiita_marker/case_fold_switch.inc +4327 -0
- data/ext/qiita_marker/chunk.h +135 -0
- data/ext/qiita_marker/cmark-gfm-core-extensions.h +54 -0
- data/ext/qiita_marker/cmark-gfm-extension_api.h +736 -0
- data/ext/qiita_marker/cmark-gfm-extensions_export.h +42 -0
- data/ext/qiita_marker/cmark-gfm.h +817 -0
- data/ext/qiita_marker/cmark-gfm_export.h +42 -0
- data/ext/qiita_marker/cmark-gfm_version.h +7 -0
- data/ext/qiita_marker/cmark.c +55 -0
- data/ext/qiita_marker/cmark_ctype.c +44 -0
- data/ext/qiita_marker/cmark_ctype.h +33 -0
- data/ext/qiita_marker/commonmark.c +529 -0
- data/ext/qiita_marker/config.h +76 -0
- data/ext/qiita_marker/core-extensions.c +27 -0
- data/ext/qiita_marker/entities.inc +2138 -0
- data/ext/qiita_marker/ext_scanners.c +879 -0
- data/ext/qiita_marker/ext_scanners.h +24 -0
- data/ext/qiita_marker/extconf.rb +7 -0
- data/ext/qiita_marker/footnotes.c +63 -0
- data/ext/qiita_marker/footnotes.h +27 -0
- data/ext/qiita_marker/houdini.h +57 -0
- data/ext/qiita_marker/houdini_href_e.c +100 -0
- data/ext/qiita_marker/houdini_html_e.c +66 -0
- data/ext/qiita_marker/houdini_html_u.c +149 -0
- data/ext/qiita_marker/html.c +486 -0
- data/ext/qiita_marker/html.h +27 -0
- data/ext/qiita_marker/inlines.c +1691 -0
- data/ext/qiita_marker/inlines.h +29 -0
- data/ext/qiita_marker/iterator.c +159 -0
- data/ext/qiita_marker/iterator.h +26 -0
- data/ext/qiita_marker/latex.c +466 -0
- data/ext/qiita_marker/linked_list.c +37 -0
- data/ext/qiita_marker/man.c +278 -0
- data/ext/qiita_marker/map.c +122 -0
- data/ext/qiita_marker/map.h +41 -0
- data/ext/qiita_marker/node.c +979 -0
- data/ext/qiita_marker/node.h +125 -0
- data/ext/qiita_marker/parser.h +58 -0
- data/ext/qiita_marker/plaintext.c +235 -0
- data/ext/qiita_marker/plugin.c +36 -0
- data/ext/qiita_marker/plugin.h +34 -0
- data/ext/qiita_marker/qiita_marker.c +1321 -0
- data/ext/qiita_marker/qiita_marker.h +16 -0
- data/ext/qiita_marker/references.c +42 -0
- data/ext/qiita_marker/references.h +26 -0
- data/ext/qiita_marker/registry.c +63 -0
- data/ext/qiita_marker/registry.h +24 -0
- data/ext/qiita_marker/render.c +205 -0
- data/ext/qiita_marker/render.h +62 -0
- data/ext/qiita_marker/scanners.c +10520 -0
- data/ext/qiita_marker/scanners.h +62 -0
- data/ext/qiita_marker/scanners.re +341 -0
- data/ext/qiita_marker/strikethrough.c +167 -0
- data/ext/qiita_marker/strikethrough.h +9 -0
- data/ext/qiita_marker/syntax_extension.c +149 -0
- data/ext/qiita_marker/syntax_extension.h +34 -0
- data/ext/qiita_marker/table.c +822 -0
- data/ext/qiita_marker/table.h +12 -0
- data/ext/qiita_marker/tagfilter.c +60 -0
- data/ext/qiita_marker/tagfilter.h +8 -0
- data/ext/qiita_marker/tasklist.c +156 -0
- data/ext/qiita_marker/tasklist.h +8 -0
- data/ext/qiita_marker/utf8.c +317 -0
- data/ext/qiita_marker/utf8.h +35 -0
- data/ext/qiita_marker/xml.c +181 -0
- data/lib/qiita_marker/config.rb +52 -0
- data/lib/qiita_marker/node/inspect.rb +57 -0
- data/lib/qiita_marker/node.rb +83 -0
- data/lib/qiita_marker/renderer/html_renderer.rb +252 -0
- data/lib/qiita_marker/renderer.rb +135 -0
- data/lib/qiita_marker/version.rb +5 -0
- data/lib/qiita_marker.rb +45 -0
- data/qiita_marker.gemspec +40 -0
- data/test/benchmark.rb +32 -0
- data/test/fixtures/curly.md +1 -0
- data/test/fixtures/dingus.md +10 -0
- data/test/fixtures/strong.md +1 -0
- data/test/fixtures/table.md +10 -0
- data/test/test_attributes.rb +24 -0
- data/test/test_basics.rb +35 -0
- data/test/test_commands.rb +72 -0
- data/test/test_commonmark.rb +36 -0
- data/test/test_doc.rb +130 -0
- data/test/test_encoding.rb +23 -0
- data/test/test_extensions.rb +116 -0
- data/test/test_footnotes.rb +60 -0
- data/test/test_gc.rb +47 -0
- data/test/test_helper.rb +71 -0
- data/test/test_linebreaks.rb +15 -0
- data/test/test_maliciousness.rb +262 -0
- data/test/test_node.rb +89 -0
- data/test/test_options.rb +37 -0
- data/test/test_pathological_inputs.rb +94 -0
- data/test/test_plaintext.rb +46 -0
- data/test/test_renderer.rb +47 -0
- data/test/test_smartpunct.rb +27 -0
- data/test/test_spec.rb +30 -0
- data/test/test_tasklists.rb +43 -0
- data/test/test_xml.rb +107 -0
- metadata +313 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b4222f9db082f683cdabb0d9d42a255ab4b689fe19cdb178efe4feccea10439d
|
4
|
+
data.tar.gz: 49e29b6cee35cb99e550f65ed830e6cd83448c7b058c09c3383c97722df86b5c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c74fe17ddee587a42758795f9a9ff9bd5982b7c284a247615af864e6fdad8dd1b6708b55eadbec2b9eaf893e3d9eeb5e03c72d62da78598322b90d01adc8cc84
|
7
|
+
data.tar.gz: f8180555767d3aa6134f7dae895d06fdda9f4b655d41d6872b6234dbe073787debd4fd0b6956da261f149b28d821d95c6e0b947e7049307a92267205e24a5a9c
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright 2021 Increments Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Qiita Marker
|
2
|
+
|
3
|
+
[![Build Status](https://github.com/increments/qiita-marker/actions/workflows/test.yml/badge.svg)](https://github.com/increments/qiita-marker/actions/workflows/test.yml)
|
4
|
+
|
5
|
+
:warning: This library is still in the testing phase. As such, development may be halted.
|
6
|
+
|
7
|
+
Qiita Marker is a Ruby library for Markdown processing, based on [CommonMarker](https://github.com/gjtorikian/commonmarker).
|
8
|
+
It will be a core module of [Qiita Markdown](https://github.com/increments/qiita-markdown) gem and not intended for direct use. If you are looking for Qiita-specified markdown processor, use [Qiita Markdown](https://github.com/increments/qiita-markdown) gem.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
Please see [CommonMarker's Usage](https://github.com/gjtorikian/commonmarker#usage).
|
13
|
+
|
14
|
+
## Contributing
|
15
|
+
|
16
|
+
If you have suggestion or modification to this repository, please create an Issue or Pull Request.
|
17
|
+
|
18
|
+
### How to develop
|
19
|
+
|
20
|
+
```
|
21
|
+
# Clone repository
|
22
|
+
$ git clone git@github.com:increments/qiita_marker.git
|
23
|
+
$ cd qiita_marker
|
24
|
+
|
25
|
+
# Setup development environment
|
26
|
+
$ ./script/bootstrap
|
27
|
+
|
28
|
+
# Run test
|
29
|
+
$ bundle exec rake test
|
30
|
+
```
|
31
|
+
|
32
|
+
#### with Docker
|
33
|
+
|
34
|
+
```
|
35
|
+
# Clone repository
|
36
|
+
$ git clone git@github.com:increments/qiita_marker.git
|
37
|
+
$ cd qiita_marker
|
38
|
+
|
39
|
+
# Setup development environment
|
40
|
+
$ docker compose build
|
41
|
+
$ docker compose up -d
|
42
|
+
$ docker compose run --rm app ./script/bootstrap
|
43
|
+
|
44
|
+
# Run test
|
45
|
+
$ docker compose run --rm rake test
|
46
|
+
```
|
47
|
+
|
48
|
+
## License
|
49
|
+
|
50
|
+
Please see [LICENSE.txt](/LICENSE.txt).
|
data/Rakefile
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'rake/clean'
|
5
|
+
require 'rake/extensiontask'
|
6
|
+
require 'digest/md5'
|
7
|
+
|
8
|
+
host_os = RbConfig::CONFIG['host_os']
|
9
|
+
require 'devkit' if host_os == 'mingw32'
|
10
|
+
|
11
|
+
task default: [:test]
|
12
|
+
|
13
|
+
# Gem Spec
|
14
|
+
gem_spec = Gem::Specification.load('qiita_marker.gemspec')
|
15
|
+
|
16
|
+
# Ruby Extension
|
17
|
+
Rake::ExtensionTask.new('qiita_marker', gem_spec) do |ext|
|
18
|
+
ext.lib_dir = File.join('lib', 'qiita_marker')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Packaging
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
# Testing
|
25
|
+
require 'rake/testtask'
|
26
|
+
|
27
|
+
Rake::TestTask.new('test:unit') do |t|
|
28
|
+
t.libs << 'lib'
|
29
|
+
t.libs << 'test'
|
30
|
+
t.pattern = 'test/test_*.rb'
|
31
|
+
t.verbose = true
|
32
|
+
t.warning = false
|
33
|
+
end
|
34
|
+
|
35
|
+
task 'test:unit' => :compile
|
36
|
+
|
37
|
+
desc 'Run unit and conformance tests'
|
38
|
+
task test: %w[test:unit]
|
39
|
+
|
40
|
+
require 'rubocop/rake_task'
|
41
|
+
|
42
|
+
RuboCop::RakeTask.new(:rubocop)
|
43
|
+
|
44
|
+
desc 'Run benchmarks'
|
45
|
+
task :benchmark do
|
46
|
+
if ENV['FETCH_PROGIT']
|
47
|
+
`rm -rf test/progit`
|
48
|
+
`git clone https://github.com/progit/progit.git test/progit`
|
49
|
+
langs = %w[ar az be ca cs de en eo es es-ni fa fi fr hi hu id it ja ko mk nl no-nb pl pt-br ro ru sr th tr uk vi zh zh-tw]
|
50
|
+
langs.each do |lang|
|
51
|
+
`cat test/progit/#{lang}/*/*.markdown >> test/benchinput.md`
|
52
|
+
end
|
53
|
+
end
|
54
|
+
$LOAD_PATH.unshift 'lib'
|
55
|
+
load 'test/benchmark.rb'
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'Match C style of cmark'
|
59
|
+
task :format do
|
60
|
+
sh 'clang-format -style llvm -i ext/qiita_marker/*.c ext/qiita_marker/*.h'
|
61
|
+
end
|
62
|
+
|
63
|
+
# Documentation
|
64
|
+
require 'rdoc/task'
|
65
|
+
|
66
|
+
desc 'Generate API documentation'
|
67
|
+
RDoc::Task.new do |rd|
|
68
|
+
rd.rdoc_dir = 'docs'
|
69
|
+
rd.main = 'README.md'
|
70
|
+
rd.rdoc_files.include 'README.md', 'lib/**/*.rb', 'ext/qiita_marker/qiita_marker.c'
|
71
|
+
|
72
|
+
rd.options << '--markup tomdoc'
|
73
|
+
rd.options << '--inline-source'
|
74
|
+
rd.options << '--line-numbers'
|
75
|
+
rd.options << '--all'
|
76
|
+
rd.options << '--fileboxes'
|
77
|
+
end
|
78
|
+
|
79
|
+
desc 'Generate the documentation and run a web server'
|
80
|
+
task serve: [:rdoc] do
|
81
|
+
require 'webrick'
|
82
|
+
|
83
|
+
puts 'Navigate to http://localhost:3000 to see the docs'
|
84
|
+
|
85
|
+
server = WEBrick::HTTPServer.new Port: 3000
|
86
|
+
server.mount '/', WEBrick::HTTPServlet::FileHandler, 'docs'
|
87
|
+
trap('INT') { server.stop }
|
88
|
+
server.start
|
89
|
+
end
|
90
|
+
|
91
|
+
desc 'Generate and publish docs to gh-pages'
|
92
|
+
task publish: [:rdoc] do
|
93
|
+
require 'tmpdir'
|
94
|
+
require 'shellwords'
|
95
|
+
|
96
|
+
Dir.mktmpdir do |tmp|
|
97
|
+
system "mv docs/* #{tmp}"
|
98
|
+
system 'git checkout origin/gh-pages'
|
99
|
+
system 'rm -rf *'
|
100
|
+
system "mv #{tmp}/* ."
|
101
|
+
message = Shellwords.escape("Site updated at #{Time.now.utc}")
|
102
|
+
system 'git add .'
|
103
|
+
system "git commit -am #{message}"
|
104
|
+
system 'git push origin gh-pages --force'
|
105
|
+
system 'git checkout master'
|
106
|
+
system 'echo yolo'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Custom tasks
|
111
|
+
Dir.glob('tasks/*.rake').each do |f|
|
112
|
+
load f
|
113
|
+
end
|
data/bin/qiita_marker
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
8
|
+
require 'qiita_marker'
|
9
|
+
|
10
|
+
root = File.expand_path('..', __dir__)
|
11
|
+
$LOAD_PATH.unshift File.expand_path('lib', root)
|
12
|
+
|
13
|
+
def parse_options
|
14
|
+
options = OpenStruct.new
|
15
|
+
extensions = QiitaMarker.extensions
|
16
|
+
parse_options = QiitaMarker::Config::OPTS.fetch(:parse)
|
17
|
+
render_options = QiitaMarker::Config::OPTS.fetch(:render)
|
18
|
+
format_options = QiitaMarker::Config::OPTS.fetch(:format)
|
19
|
+
|
20
|
+
options.active_extensions = []
|
21
|
+
options.active_parse_options = [:DEFAULT]
|
22
|
+
options.active_render_options = [:DEFAULT]
|
23
|
+
options.output_format = :html
|
24
|
+
|
25
|
+
option_parser = OptionParser.new do |opts|
|
26
|
+
opts.banner = 'Usage: qiita_marker [--html-renderer] [--extension=EXTENSION]'
|
27
|
+
opts.separator ' [--to=FORMAT]'
|
28
|
+
opts.separator ' [--parse-option=OPTION]'
|
29
|
+
opts.separator ' [--render-option=OPTION]'
|
30
|
+
opts.separator ' [FILE..]'
|
31
|
+
opts.separator ''
|
32
|
+
opts.separator 'Convert one or more CommonMark files to HTML and write to standard output.'
|
33
|
+
opts.separator 'If no FILE argument is provided, text will be read from STDIN.'
|
34
|
+
opts.separator ''
|
35
|
+
|
36
|
+
opts.on('--extension=EXTENSION', Array, 'Use EXTENSION for parsing and HTML output (unless --html-renderer is specified)') do |values|
|
37
|
+
values.each do |value|
|
38
|
+
if extensions.include?(value)
|
39
|
+
options.active_extensions << value.to_sym
|
40
|
+
else
|
41
|
+
abort("extension '#{value}' not found")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on('-h', '--help', 'Prints this help') do
|
47
|
+
puts opts
|
48
|
+
puts
|
49
|
+
puts "Available formats: #{format_options.join(', ')}"
|
50
|
+
puts "Available extentions: #{extensions.join(', ')}"
|
51
|
+
puts "Available parse options: #{parse_options.keys.join(', ')}"
|
52
|
+
puts "Available render options: #{render_options.keys.join(', ')}"
|
53
|
+
puts
|
54
|
+
puts 'See the README for more information on these.'
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on('-tFORMAT', '--to=FORMAT', String, 'Specify output FORMAT') do |value|
|
59
|
+
value = value.to_sym
|
60
|
+
if format_options.include?(value)
|
61
|
+
options.output_format = value
|
62
|
+
else
|
63
|
+
abort("format '#{value}' not found")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on('--html-renderer', 'Use the HtmlRenderer renderer rather than the native C renderer (only valid when format is html)') do
|
68
|
+
options.renderer = true
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on('--parse-option=OPTION', Array, 'OPTION passed during parsing') do |values|
|
72
|
+
values.each do |value|
|
73
|
+
if parse_options.key?(value.to_sym)
|
74
|
+
options.active_parse_options << value.to_sym
|
75
|
+
else
|
76
|
+
abort("parse-option '#{value}' not found")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on('--render-option=OPTION', Array, 'OPTION passed during rendering') do |values|
|
82
|
+
values.each do |value|
|
83
|
+
if render_options.key?(value.to_sym)
|
84
|
+
options.active_render_options << value.to_sym
|
85
|
+
else
|
86
|
+
abort("render-option '#{value}' not found")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on('-v', '--version', 'Version information') do
|
92
|
+
puts "qiita_marker #{QiitaMarker::VERSION}"
|
93
|
+
exit
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
option_parser.parse!
|
98
|
+
|
99
|
+
options
|
100
|
+
end
|
101
|
+
|
102
|
+
options = parse_options
|
103
|
+
|
104
|
+
abort("format '#{options.output_format}' does not support using the HtmlRenderer renderer") if
|
105
|
+
options.renderer && options.output_format != :html
|
106
|
+
|
107
|
+
doc = QiitaMarker.render_doc(ARGF.read, options.active_parse_options, options.active_extensions)
|
108
|
+
|
109
|
+
case options.output_format
|
110
|
+
when :html
|
111
|
+
if options.renderer
|
112
|
+
renderer = QiitaMarker::HtmlRenderer.new(options: options.active_render_options, extensions: options.active_extensions)
|
113
|
+
$stdout.write(renderer.render(doc))
|
114
|
+
else
|
115
|
+
$stdout.write(doc.to_html(options.active_render_options, options.active_extensions))
|
116
|
+
end
|
117
|
+
when :xml
|
118
|
+
$stdout.write(doc.to_xml(options.active_render_options))
|
119
|
+
when :commonmark
|
120
|
+
$stdout.write(doc.to_commonmark(options.active_render_options))
|
121
|
+
when :plaintext
|
122
|
+
$stdout.write(doc.to_plaintext(options.active_render_options))
|
123
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <stdint.h>
|
4
|
+
#include "cmark-gfm.h"
|
5
|
+
#include "cmark-gfm-extension_api.h"
|
6
|
+
|
7
|
+
static struct arena_chunk {
|
8
|
+
size_t sz, used;
|
9
|
+
uint8_t push_point;
|
10
|
+
void *ptr;
|
11
|
+
struct arena_chunk *prev;
|
12
|
+
} *A = NULL;
|
13
|
+
|
14
|
+
static struct arena_chunk *alloc_arena_chunk(size_t sz, struct arena_chunk *prev) {
|
15
|
+
struct arena_chunk *c = (struct arena_chunk *)calloc(1, sizeof(*c));
|
16
|
+
if (!c)
|
17
|
+
abort();
|
18
|
+
c->sz = sz;
|
19
|
+
c->ptr = calloc(1, sz);
|
20
|
+
if (!c->ptr)
|
21
|
+
abort();
|
22
|
+
c->prev = prev;
|
23
|
+
return c;
|
24
|
+
}
|
25
|
+
|
26
|
+
void cmark_arena_push(void) {
|
27
|
+
if (!A)
|
28
|
+
return;
|
29
|
+
A->push_point = 1;
|
30
|
+
A = alloc_arena_chunk(10240, A);
|
31
|
+
}
|
32
|
+
|
33
|
+
int cmark_arena_pop(void) {
|
34
|
+
if (!A)
|
35
|
+
return 0;
|
36
|
+
while (A && !A->push_point) {
|
37
|
+
free(A->ptr);
|
38
|
+
struct arena_chunk *n = A->prev;
|
39
|
+
free(A);
|
40
|
+
A = n;
|
41
|
+
}
|
42
|
+
if (A)
|
43
|
+
A->push_point = 0;
|
44
|
+
return 1;
|
45
|
+
}
|
46
|
+
|
47
|
+
static void init_arena(void) {
|
48
|
+
A = alloc_arena_chunk(4 * 1048576, NULL);
|
49
|
+
}
|
50
|
+
|
51
|
+
void cmark_arena_reset(void) {
|
52
|
+
while (A) {
|
53
|
+
free(A->ptr);
|
54
|
+
struct arena_chunk *n = A->prev;
|
55
|
+
free(A);
|
56
|
+
A = n;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
static void *arena_calloc(size_t nmem, size_t size) {
|
61
|
+
if (!A)
|
62
|
+
init_arena();
|
63
|
+
|
64
|
+
size_t sz = nmem * size + sizeof(size_t);
|
65
|
+
|
66
|
+
// Round allocation sizes to largest integer size to
|
67
|
+
// ensure returned memory is correctly aligned
|
68
|
+
const size_t align = sizeof(size_t) - 1;
|
69
|
+
sz = (sz + align) & ~align;
|
70
|
+
|
71
|
+
if (sz > A->sz) {
|
72
|
+
A->prev = alloc_arena_chunk(sz, A->prev);
|
73
|
+
return (uint8_t *) A->prev->ptr + sizeof(size_t);
|
74
|
+
}
|
75
|
+
if (sz > A->sz - A->used) {
|
76
|
+
A = alloc_arena_chunk(A->sz + A->sz / 2, A);
|
77
|
+
}
|
78
|
+
void *ptr = (uint8_t *) A->ptr + A->used;
|
79
|
+
A->used += sz;
|
80
|
+
*((size_t *) ptr) = sz - sizeof(size_t);
|
81
|
+
return (uint8_t *) ptr + sizeof(size_t);
|
82
|
+
}
|
83
|
+
|
84
|
+
static void *arena_realloc(void *ptr, size_t size) {
|
85
|
+
if (!A)
|
86
|
+
init_arena();
|
87
|
+
|
88
|
+
void *new_ptr = arena_calloc(1, size);
|
89
|
+
if (ptr)
|
90
|
+
memcpy(new_ptr, ptr, ((size_t *) ptr)[-1]);
|
91
|
+
return new_ptr;
|
92
|
+
}
|
93
|
+
|
94
|
+
static void arena_free(void *ptr) {
|
95
|
+
(void) ptr;
|
96
|
+
/* no-op */
|
97
|
+
}
|
98
|
+
|
99
|
+
cmark_mem CMARK_ARENA_MEM_ALLOCATOR = {arena_calloc, arena_realloc, arena_free};
|
100
|
+
|
101
|
+
cmark_mem *cmark_get_arena_mem_allocator() {
|
102
|
+
return &CMARK_ARENA_MEM_ALLOCATOR;
|
103
|
+
}
|