|
| 1 | +namespace Pandoc |
| 2 | +{ |
| 3 | + using System; |
| 4 | + using System.IO; |
| 5 | + using System.Text; |
| 6 | + using System.Runtime.InteropServices; |
| 7 | + |
| 8 | + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| 9 | + delegate int Reader(IntPtr data); |
| 10 | + |
| 11 | + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
| 12 | + delegate void Writer(IntPtr data, int length); |
| 13 | + |
| 14 | + class Native |
| 15 | + { |
| 16 | + [DllImport("libpandoc", CallingConvention=CallingConvention.Cdecl)] |
| 17 | + public static extern void pandoc_init(); |
| 18 | + |
| 19 | + [DllImport("libpandoc", CallingConvention=CallingConvention.Cdecl)] |
| 20 | + public static extern void pandoc_exit(); |
| 21 | + |
| 22 | + [DllImport("libpandoc", CallingConvention=CallingConvention.Cdecl)] |
| 23 | + public static extern string pandoc(int bufferSize, |
| 24 | + byte[] inputFormat, |
| 25 | + byte[] outputFormat, |
| 26 | + byte[] settings, |
| 27 | + Reader reader, Writer writer); |
| 28 | + } |
| 29 | + |
| 30 | + public class PandocException : Exception |
| 31 | + { |
| 32 | + public PandocException(string message) : base(message) |
| 33 | + { |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + public class Processor : IDisposable |
| 38 | + { |
| 39 | + const int charSize = 1024; |
| 40 | + const int bytesPerChar = 4; |
| 41 | + const int byteSize = bytesPerChar * charSize; |
| 42 | + char[] chars; |
| 43 | + byte[] bytes; |
| 44 | + Encoding encoding; |
| 45 | + |
| 46 | + public Processor() |
| 47 | + { |
| 48 | + chars = new char[charSize]; |
| 49 | + bytes = new byte[byteSize]; |
| 50 | + encoding = Encoding.UTF8; |
| 51 | + Native.pandoc_init(); |
| 52 | + } |
| 53 | + |
| 54 | + public void Process(string source, string target, |
| 55 | + TextReader input, TextWriter output) |
| 56 | + { |
| 57 | + Process(source, target, null, input, output); |
| 58 | + } |
| 59 | + |
| 60 | + byte[] Bytes(string text) |
| 61 | + { |
| 62 | + if (text != null) { |
| 63 | + byte[] bytes = encoding.GetBytes(text); |
| 64 | + byte[] result = new byte[bytes.Length + 1]; |
| 65 | + for (var i = 0; i < bytes.Length; i++) { |
| 66 | + result[i] = bytes[i]; |
| 67 | + } |
| 68 | + return result; |
| 69 | + } else { |
| 70 | + return new byte[0]; |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + public void Process(string source, string target, string config, |
| 75 | + TextReader input, TextWriter output) |
| 76 | + { |
| 77 | + Reader reader = |
| 78 | + delegate (IntPtr data) |
| 79 | + { |
| 80 | + int c = input.ReadBlock(chars, 0, charSize); |
| 81 | + int b = encoding.GetBytes(chars, 0, c, bytes, 0); |
| 82 | + Marshal.Copy(bytes, 0, data, b); |
| 83 | + return b; |
| 84 | + }; |
| 85 | + Writer writer = |
| 86 | + delegate (IntPtr data, int length) |
| 87 | + { |
| 88 | + if (length > 0) { |
| 89 | + Marshal.Copy(data, bytes, 0, length); |
| 90 | + int c = encoding.GetChars(bytes, 0, length, chars, 0); |
| 91 | + output.Write(chars, 0, c); |
| 92 | + } |
| 93 | + }; |
| 94 | + string err = Native.pandoc(byteSize, |
| 95 | + Bytes(source), |
| 96 | + Bytes(target), |
| 97 | + Bytes(config), |
| 98 | + reader, |
| 99 | + writer); |
| 100 | + if (err != null) { |
| 101 | + throw new PandocException(err); |
| 102 | + } |
| 103 | + } |
| 104 | + |
| 105 | + public void Dispose() |
| 106 | + { |
| 107 | + Native.pandoc_exit(); |
| 108 | + } |
| 109 | + } |
| 110 | +} |
0 commit comments