forked from ArtifexSoftware/Ghostscript.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGhostscriptStdIO.cs
More file actions
231 lines (187 loc) · 7.6 KB
/
GhostscriptStdIO.cs
File metadata and controls
231 lines (187 loc) · 7.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//
// GhostscriptStdIO.cs
// This file is part of Ghostscript.NET library
//
// Author: Josip Habjan (habjan@gmail.com, http://www.linkedin.com/in/habjan)
// Copyright (c) 2013-2016 by Josip Habjan. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace Ghostscript.NET
{
/// <summary>
/// Represents a base Ghostscript standard input output handler.
/// </summary>
public abstract class GhostscriptStdIO
{
#region Internal variables
internal gsapi_stdio_callback _std_in = null;
internal gsapi_stdio_callback _std_out = null;
internal gsapi_stdio_callback _std_err = null;
#endregion
#region Private variables
private StringBuilder _input = new StringBuilder();
#endregion
#region Constructor
/// <summary>
/// Initializes a new instance of the Ghostscript.NET.GhostscriptStdIO class.
/// </summary>
/// <param name="handleStdIn">Whether or not to handle Ghostscript standard input.</param>
/// <param name="handleStdOut">Whether or not to handle Ghostscript standard output.</param>
/// <param name="handleStdErr">Whether or not to handle Ghostscript standard errors.</param>
public GhostscriptStdIO(bool handleStdIn, bool handleStdOut, bool handleStdErr)
{
// check if we need to handle standard input
if (handleStdIn)
{
// attach standard input handler
_std_in = new gsapi_stdio_callback(gs_std_in);
}
// check if we need to handle standard output
if (handleStdOut)
{
// attach standard output handler
_std_out = new gsapi_stdio_callback(gs_std_out);
}
// check if we need to handle errors
if (handleStdErr)
{
// attach error handler
_std_err = new gsapi_stdio_callback(gs_std_err);
}
}
#endregion
#region gs_std_in
/// <summary>
/// Standard input handler.
/// </summary>
/// <param name="handle">Standard input handle.</param>
/// <param name="pointer">Pointer to a memroy block.</param>
/// <param name="count">Number of bytes that standard input expects.</param>
/// <returns>Number of bytes returned.</returns>
private int gs_std_in(IntPtr handle, IntPtr pointer, int count)
{
// check if we have anything in the local input cache
if (_input.Length == 0)
{
string input = string.Empty;
// ask handler owner for the input data
this.StdIn(out input, count);
// check if we have input
if (!string.IsNullOrEmpty(input))
{
// add the input to the local cache
_input.Append(input);
}
else
{
// we don't have any input
return 0;
}
}
// check if the stdin expects more data than we have at the moment
if (count > _input.Length)
{
// locally set the count to a length of the data we have
count = _input.Length;
}
int position = 0;
// loop through data
while (position < count)
{
// get single character
char c = _input[position];
// write single character to the expected input memory block
Marshal.WriteByte(pointer, position, (byte)c);
position++;
// break if we got to the new line
if (c == '\n')
{
break;
}
}
// remove written data out from the cached input
_input = _input.Remove(0, position);
// return number of bytes written
return position;
}
#endregion
#region gs_std_out
/// <summary>
/// Handles standard output.
/// </summary>
/// <param name="handle">Standard output handle.</param>
/// <param name="pointer">Pointer to a memroy block.</param>
/// <param name="count">Number of bytes that standard output writes.</param>
/// <returns>Number of bytes read.</returns>
private int gs_std_out(IntPtr handle, IntPtr pointer, int count)
{
// read out the standard output data
string output = Marshal.PtrToStringAnsi(pointer, count);
// replace line feeds with the standard windows new line
output = output.Replace("\n", "\r\n");
// send read out data to the handler owner
this.StdOut(output);
// return number of bytes read
return count;
}
#endregion
#region gs_std_err
/// <summary>
/// Handles errors.
/// </summary>
/// <param name="handle">Errors handle.</param>
/// <param name="pointer">Pointer to a memory block.</param>
/// <param name="count">Number of bytes standard error writes.</param>
/// <returns>Number of bytes read.</returns>
private int gs_std_err(IntPtr handle, IntPtr pointer, int count)
{
// read out the standard error data
string errors = Marshal.PtrToStringAnsi(pointer, count);
// replace line feeds with the standard windows new line
errors = errors.Replace("\n", "\r\n");
// send read out data to the handler owner
this.StdError(errors);
// return number of bytes read
return count;
}
#endregion
#region Abstract functions
/// <summary>
/// Abstract standard input method.
/// </summary>
/// <param name="input">Input data.</param>
/// <param name="count">Expected size of the input data.</param>
public abstract void StdIn(out string input, int count);
/// <summary>
/// Abstract standard output method.
/// </summary>
/// <param name="output">Output data.</param>
public abstract void StdOut(string output);
/// <summary>
/// Abstract standard error method.
/// </summary>
/// <param name="error">Error data.</param>
public abstract void StdError(string error);
#endregion
}
}