Skip to content

Instantly share code, notes, and snippets.

@FSX
Created August 23, 2011 21:54
Show Gist options
  • Save FSX/1166695 to your computer and use it in GitHub Desktop.
Save FSX/1166695 to your computer and use it in GitHub Desktop.
Ctypes port of Misaka (https://github.com/FSX/misaka)
import time
import os.path as path
import misaka
import misaka_ctypes
class Benchmark(object):
def __init__(self, name):
self._name = name
def __call__(self, func):
def wrapper(*args, **kwargs):
start = time.clock()
func(*args, **kwargs)
end = time.clock()
return end - start
return wrapper
@Benchmark('Misaka')
def benchmark_misaka(text):
misaka.html(text)
@Benchmark('Misaka Ctypes')
def benchmark_misaka_ctypes(text):
misaka_ctypes.html(text)
if __name__ == '__main__':
with open(path.join(path.dirname(__file__), 'markdown-syntax.md'), 'r') as fd:
text = fd.read()
loops = 10000
totals = []
methods = [
('Misaka', benchmark_misaka),
('Misaka Ctypes', benchmark_misaka_ctypes),
]
print('Parsing the Markdown Syntax document %s times...' % loops)
for i, method in enumerate(methods):
total = 0
for nth in range(0, loops):
total += method[1](text)
print('%s: %gs' % (method[0], total))
from ctypes import byref, memset, sizeof, c_char_p, c_uint
from sundown import sd_callbacks, html_renderopt, bufnew, \
bufputs, sd_markdown, bufnullterm, bufrelease, sdhtml_renderer, \
sdhtml_toc_renderer, sdhtml_smartypants
__version__ = '0.5.0'
# Markdown extensions
EXT_NO_INTRA_EMPHASIS = (1 << 0)
EXT_TABLES = (1 << 1)
EXT_FENCED_CODE = (1 << 2)
EXT_AUTOLINK = (1 << 3)
EXT_STRIKETHROUGH = (1 << 4)
EXT_LAX_HTML_BLOCKS = (1 << 5)
EXT_SPACE_HEADERS = (1 << 6)
EXT_SUPERSCRIPT = (1 << 7)
# HTML Render flags
HTML_SKIP_HTML = (1 << 0)
HTML_SKIP_STYLE = (1 << 1)
HTML_SKIP_IMAGES = (1 << 2)
HTML_SKIP_LINKS = (1 << 3)
HTML_EXPAND_TABS = (1 << 5)
HTML_SAFELINK = (1 << 7)
HTML_TOC = (1 << 8)
HTML_HARD_WRAP = (1 << 9)
HTML_GITHUB_BLOCKCODE = (1 << 10)
HTML_USE_XHTML = (1 << 11)
# Extra HTML render flags - these are not from Sundown
HTML_SMARTYPANTS = (1 << 12) # An extra flag to enabled Smartypants
HTML_TOC_TREE = (1 << 13) # Only render a table of contents tree
def html(text, extensions=0, render_flags=0):
callbacks = sd_callbacks()
options = html_renderopt()
if render_flags & HTML_TOC_TREE:
sdhtml_toc_renderer(callbacks, options)
else:
sdhtml_renderer(callbacks, options, render_flags)
ib = bufnew(128)
ob = bufnew(128)
bufputs(ib, text)
sd_markdown(ob, ib, extensions, byref(callbacks), byref(options))
if render_flags & HTML_SMARTYPANTS:
sb = bufnew(128)
sdhtml_smartypants(sb, ob)
bufrelease(ob)
ob = sb
bufnullterm(ob)
data = ob.contents.data
bufrelease(ob)
bufrelease(ib)
return data
# You need the shared library of Sundown.
#
# - Download the latest sources from: https://github.com/tanoku/sundown
# - Compile everything with the `make` command.
# - Put `libsundown.so.1` in the same directory as `misaka_ctypes.py` and `sundown.py`
import math
from ctypes import cdll, Structure, c_char_p, c_size_t, c_int, CFUNCTYPE, \
c_uint, POINTER, c_void_p
sundown = cdll.LoadLibrary('./libsundown.so.1')
class buf(Structure):
_fields_ = [
('data', c_char_p),
('size', c_size_t),
('asize', c_size_t),
('unit', c_size_t),
('ref', c_int)
]
buf_p = POINTER(buf)
class _toc_data(Structure):
_fields_ = [
('header_count', c_int),
('current_level', c_int)
]
LINK_ATTRIBUTES = CFUNCTYPE(None, buf_p, buf_p, buf_p, c_void_p)
class html_renderopt(Structure):
_fields_ = [
('toc_data', _toc_data),
('flags', c_uint),
('link_attributes', LINK_ATTRIBUTES)
]
html_renderopt_p = POINTER(html_renderopt)
render_callbacks = {
# Block level callbacks
'blockcode': CFUNCTYPE(None, buf_p, buf_p, buf_p, c_void_p),
'blockquote': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'blockhtml': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'header': CFUNCTYPE(None, buf_p, buf_p, c_int, c_void_p),
'hrule': CFUNCTYPE(None, buf_p, c_void_p),
'list': CFUNCTYPE(None, buf_p, buf_p, c_int, c_void_p),
'listitem': CFUNCTYPE(None, buf_p, buf_p, c_int, c_void_p),
'paragraph': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'table': CFUNCTYPE(None, buf_p, buf_p, buf_p, c_void_p),
'table_row': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'table_cell': CFUNCTYPE(None, buf_p, buf_p, c_int, c_void_p),
# Span level callbacks
'autolink': CFUNCTYPE(None, buf_p, buf_p, c_int, c_void_p),
'codespan': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'double_emphasis': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'emphasis': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'image': CFUNCTYPE(None, buf_p, buf_p, buf_p, buf_p, c_void_p),
'linebreak': CFUNCTYPE(None, buf_p, c_void_p),
'link': CFUNCTYPE(None, buf_p, buf_p, buf_p, buf_p, c_void_p),
'raw_html_tag': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'triple_emphasis': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'strikethrough': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'superscript': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
# Low level callbacks
'entity': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
'normal_text': CFUNCTYPE(None, buf_p, buf_p, c_void_p),
# Header and footer
'doc_header': CFUNCTYPE(None, buf_p, c_void_p),
'doc_footer': CFUNCTYPE(None, buf_p, c_void_p)
}
class sd_callbacks(Structure):
_fields_ = [
('blockcode', render_callbacks['blockcode']),
('blockquote', render_callbacks['blockquote']),
('blockhtml', render_callbacks['blockhtml']),
('header', render_callbacks['header']),
('hrule', render_callbacks['hrule']),
('list', render_callbacks['list']),
('listitem', render_callbacks['listitem']),
('paragraph', render_callbacks['paragraph']),
('table', render_callbacks['table']),
('table_row', render_callbacks['table_row']),
('table_cell', render_callbacks['table_cell']),
('autolink', render_callbacks['autolink']),
('codespan', render_callbacks['codespan']),
('double_emphasis', render_callbacks['double_emphasis']),
('emphasis', render_callbacks['emphasis']),
('image', render_callbacks['image']),
('linebreak', render_callbacks['linebreak']),
('link', render_callbacks['link']),
('raw_html_tag', render_callbacks['raw_html_tag']),
('triple_emphasis', render_callbacks['triple_emphasis']),
('strikethrough', render_callbacks['strikethrough']),
('superscript', render_callbacks['superscript']),
('entity', render_callbacks['entity']),
('normal_text', render_callbacks['normal_text']),
('doc_header', render_callbacks['doc_header']),
('doc_footer', render_callbacks['doc_footer'])
]
sd_callbacks_p = POINTER(sd_callbacks)
sundown.bufnew.argtypes = [c_size_t]
sundown.bufnew.restype = buf_p
sundown.bufgrow.argtypes = [buf_p, c_size_t]
sundown.bufgrow.restype = c_void_p
sundown.bufnullterm.argtypes = [buf_p]
sundown.bufnullterm.restype = c_void_p
sundown.bufrelease.argtypes = [buf_p]
sundown.bufrelease.restype = c_void_p
sundown.bufput.argtypes = [buf_p, c_void_p, c_size_t]
sundown.bufput.restype = c_void_p
sundown.bufputs.argtypes = [buf_p, c_char_p]
sundown.bufputs.restype = c_void_p
sundown.sdhtml_renderer.restype = c_void_p
sundown.sdhtml_renderer.argtypes = [
sd_callbacks_p,
html_renderopt_p,
c_uint
]
sundown.sdhtml_toc_renderer.restype = c_void_p
sundown.sdhtml_toc_renderer.argtypes = [
sd_callbacks_p,
html_renderopt_p
]
sundown.sdhtml_smartypants.restype = c_void_p
sundown.sdhtml_smartypants.argtypes = [buf_p, buf_p]
sundown.sd_markdown.restype = c_void_p
sundown.sd_markdown.argtypes = [
buf_p,
buf_p,
c_uint,
sd_callbacks_p,
c_void_p
]
bufnew = sundown.bufnew
bufnullterm = sundown.bufnullterm
bufrelease = sundown.bufrelease
bufput = sundown.bufput
bufputs = sundown.bufputs
sdhtml_renderer = sundown.sdhtml_renderer
sdhtml_toc_renderer = sundown.sdhtml_toc_renderer
sdhtml_smartypants = sundown.sdhtml_smartypants
sd_markdown = sundown.sd_markdown
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment