1/*
2 * convert.c --
3 *
4 *	Implements the C level procedures handling option processing
5 *	for converter transformations.
6 *
7 *
8 * Copyright (c) 1996 Andreas Kupries (a.kupries@westend.com)
9 * All rights reserved.
10 *
11 * Permission is hereby granted, without written agreement and without
12 * license or royalty fees, to use, copy, modify, and distribute this
13 * software and its documentation for any purpose, provided that the
14 * above copyright notice and the following two paragraphs appear in
15 * all copies of this software.
16 *
17 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
18 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
19 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE
20 * POSSIBILITY OF SUCH DAMAGE.
21 *
22 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
25 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
26 * ENHANCEMENTS, OR MODIFICATIONS.
27 *
28 * CVS: $Id: convert.c,v 1.10 2009/05/07 04:57:27 andreas_kupries Exp $
29 */
30
31#include "transformInt.h"
32
33/*
34 * forward declarations of all internally used procedures.
35 */
36
37static Trf_Options
38CreateOptions _ANSI_ARGS_ ((ClientData clientData));
39
40static void
41DeleteOptions _ANSI_ARGS_ ((Trf_Options options,
42			    ClientData  clientData));
43static int
44CheckOptions  _ANSI_ARGS_ ((Trf_Options            options,
45			    Tcl_Interp*            interp,
46			    CONST Trf_BaseOptions* baseOptions,
47			    ClientData             clientData));
48static int
49SetOption     _ANSI_ARGS_ ((Trf_Options    options,
50			    Tcl_Interp*    interp,
51			    CONST char*    optname,
52			    CONST Tcl_Obj* optvalue,
53			    ClientData     clientData));
54static int
55QueryOptions  _ANSI_ARGS_ ((Trf_Options options,
56			    ClientData  clientData));
57
58static void
59SeekQueryOptions  _ANSI_ARGS_ ((Tcl_Interp*          interp,
60				Trf_Options          options,
61				Trf_SeekInformation* seekInfo,
62				ClientData           clientData));
63
64
65/*
66 *------------------------------------------------------*
67 *
68 *	Trf_ConverterOptions --
69 *
70 *	------------------------------------------------*
71 *	Accessor to the set of vectors realizing option
72 *	processing for converter procedures.
73 *	------------------------------------------------*
74 *
75 *	Sideeffects:
76 *		None.
77 *
78 *	Result:
79 *		See above.
80 *
81 *------------------------------------------------------*
82 */
83
84Trf_OptionVectors*
85Trf_ConverterOptions ()
86{
87  static Trf_OptionVectors optVec = /* THREADING: constant, read-only => safe */
88    {
89      CreateOptions,
90      DeleteOptions,
91      CheckOptions,
92      NULL,      /* no string procedure for 'SetOption' */
93      SetOption,
94      QueryOptions,
95      SeekQueryOptions
96    };
97
98  return &optVec;
99}
100
101/*
102 *------------------------------------------------------*
103 *
104 *	CreateOptions --
105 *
106 *	------------------------------------------------*
107 *	Create option structure for converter transformations.
108 *	------------------------------------------------*
109 *
110 *	Sideeffects:
111 *		Allocates memory and initializes it as
112 *		option structure for converter
113 *		transformations.
114 *
115 *	Result:
116 *		A reference to the allocated block of
117 *		memory.
118 *
119 *------------------------------------------------------*
120 */
121
122static Trf_Options
123CreateOptions (clientData)
124ClientData clientData;
125{
126  Trf_ConverterOptionBlock* o;
127
128  o = (Trf_ConverterOptionBlock*) ckalloc (sizeof (Trf_ConverterOptionBlock));
129  o->mode = TRF_UNKNOWN_MODE;
130
131  return (Trf_Options) o;
132}
133
134/*
135 *------------------------------------------------------*
136 *
137 *	DeleteOptions --
138 *
139 *	------------------------------------------------*
140 *	Delete option structure of a converter transformations
141 *	------------------------------------------------*
142 *
143 *	Sideeffects:
144 *		A memory block allocated by 'CreateOptions'
145 *		is released.
146 *
147 *	Result:
148 *		None.
149 *
150 *------------------------------------------------------*
151 */
152
153static void
154DeleteOptions (options, clientData)
155Trf_Options options;
156ClientData  clientData;
157{
158  Trf_ConverterOptionBlock* o = (Trf_ConverterOptionBlock*) options;
159  ckfree ((VOID*) o);
160}
161
162/*
163 *------------------------------------------------------*
164 *
165 *	CheckOptions --
166 *
167 *	------------------------------------------------*
168 *	Check the given option structure for errors.
169 *	------------------------------------------------*
170 *
171 *	Sideeffects:
172 *		May modify the given structure to set
173 *		default values into uninitialized parts.
174 *
175 *	Result:
176 *		A standard Tcl error code.
177 *
178 *------------------------------------------------------*
179 */
180
181static int
182CheckOptions (options, interp, baseOptions, clientData)
183Trf_Options            options;
184Tcl_Interp*            interp;
185CONST Trf_BaseOptions* baseOptions;
186ClientData             clientData;
187{
188  Trf_ConverterOptionBlock* o = (Trf_ConverterOptionBlock*) options;
189
190  if (baseOptions->attach == (Tcl_Channel) NULL) /* IMMEDIATE? */ {
191    if (o->mode == TRF_UNKNOWN_MODE) {
192      Tcl_AppendResult (interp, "-mode option not set", (char*) NULL);
193      return TCL_ERROR;
194    }
195  } else /* ATTACH */ {
196    if (o->mode == TRF_UNKNOWN_MODE) {
197      o->mode = TRF_ENCODE_MODE;
198    }
199  }
200
201  return TCL_OK;
202}
203
204/*
205 *------------------------------------------------------*
206 *
207 *	SetOption --
208 *
209 *	------------------------------------------------*
210 *	Define value of given option.
211 *	------------------------------------------------*
212 *
213 *	Sideeffects:
214 *		Sets the given value into the option
215 *		structure
216 *
217 *	Result:
218 *		A standard Tcl error code.
219 *
220 *------------------------------------------------------*
221 */
222
223static int
224SetOption (options, interp, optname, optvalue, clientData)
225Trf_Options options;
226Tcl_Interp* interp;
227CONST char* optname;
228CONST Tcl_Obj* optvalue;
229ClientData  clientData;
230{
231  Trf_ConverterOptionBlock* o = (Trf_ConverterOptionBlock*) options;
232  int                     len;
233  CONST char*             value;
234
235  len = strlen (optname+1);
236
237  switch (optname [1]) {
238  case 'm':
239    if (0 != strncmp (optname, "-mode", len))
240      goto unknown_option;
241
242    value = Tcl_GetStringFromObj ((Tcl_Obj*) optvalue, NULL);
243    len   = strlen (value);
244
245    switch (value [0]) {
246    case 'e':
247      if (0 != strncmp (value, "encode", len))
248	goto unknown_mode;
249
250      o->mode = TRF_ENCODE_MODE;
251      break;
252
253    case 'd':
254      if (0 != strncmp (value, "decode", len))
255	goto unknown_mode;
256
257      o->mode = TRF_DECODE_MODE;
258      break;
259
260    default:
261    unknown_mode:
262      Tcl_AppendResult (interp, "unknown mode '", (char*) NULL);
263      Tcl_AppendResult (interp, value, (char*) NULL);
264      Tcl_AppendResult (interp, "', should be 'encode' or 'decode'", (char*) NULL);
265      return TCL_ERROR;
266      break;
267    } /* switch optvalue */
268    break;
269
270  default:
271    goto unknown_option;
272    break;
273  }
274
275  return TCL_OK;
276
277 unknown_option:
278  Tcl_AppendResult (interp, "unknown option '", (char*) NULL);
279  Tcl_AppendResult (interp, optname, (char*) NULL);
280  Tcl_AppendResult (interp, "', should be '-mode'", (char*) NULL);
281  return TCL_ERROR;
282}
283
284/*
285 *------------------------------------------------------*
286 *
287 *	QueryOptions --
288 *
289 *	------------------------------------------------*
290 *	Returns a value indicating wether the encoder or
291 *	decoder set of vectors is to be used by immediate
292 *	execution.
293 *	------------------------------------------------*
294 *
295 *	Sideeffects:
296 *		None
297 *
298 *	Result:
299 *		1 - use encoder vectors.
300 *		0 - use decoder vectors.
301 *
302 *------------------------------------------------------*
303 */
304
305static int
306QueryOptions (options, clientData)
307Trf_Options options;
308ClientData clientData;
309{
310  Trf_ConverterOptionBlock* o = (Trf_ConverterOptionBlock*) options;
311
312  return (o->mode == TRF_ENCODE_MODE ? 1 : 0);
313}
314
315/*
316 *------------------------------------------------------*
317 *
318 *	SeekQueryOptions --
319 *
320 *	------------------------------------------------*
321 *	Modifies the natural seek policy according to the
322 *	configuration of the transformation.
323 *	------------------------------------------------*
324 *
325 *	Sideeffects:
326 *		May modify 'seekInfo'.
327 *
328 *	Result:
329 *		None.
330 *
331 *------------------------------------------------------*
332 */
333
334static void
335SeekQueryOptions (interp, options, seekInfo, clientData)
336     Tcl_Interp*          interp;
337     Trf_Options          options;
338     Trf_SeekInformation* seekInfo;
339     ClientData           clientData;
340{
341  Trf_ConverterOptionBlock* o = (Trf_ConverterOptionBlock*) options;
342
343  if (o->mode == TRF_DECODE_MODE) {
344    /* The conversion is backward, swap the seek information.
345     */
346
347    int t                       = seekInfo->numBytesTransform;
348    seekInfo->numBytesTransform = seekInfo->numBytesDown;
349    seekInfo->numBytesDown      = t;
350  }
351}
352