1/*
2 * bz2_opt.c --
3 *
4 *	Implements the C level procedures handling option processing
5 *	for ZIP 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: bz2_opt.c,v 1.5 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 CreateOptions _ANSI_ARGS_ ((ClientData clientData));
38
39static void        DeleteOptions _ANSI_ARGS_ ((Trf_Options options,
40					       ClientData  clientData));
41
42static int         CheckOptions  _ANSI_ARGS_ ((Trf_Options            options,
43					       Tcl_Interp*            interp,
44					       CONST Trf_BaseOptions* baseOptions,
45					       ClientData             clientData));
46
47static int         SetOption     _ANSI_ARGS_ ((Trf_Options    options,
48					       Tcl_Interp*    interp,
49					       CONST char*    optname,
50					       CONST Tcl_Obj* optvalue,
51					       ClientData     clientData));
52
53static int         QueryOptions  _ANSI_ARGS_ ((Trf_Options options,
54					       ClientData  clientData));
55
56
57/*
58 *------------------------------------------------------*
59 *
60 *	TrfBZ2Options --
61 *
62 *	------------------------------------------------*
63 *	Accessor to the set of vectors realizing option
64 *	processing for ZIP procedures.
65 *	------------------------------------------------*
66 *
67 *	Sideeffects:
68 *		None.
69 *
70 *	Result:
71 *		See above.
72 *
73 *------------------------------------------------------*
74 */
75
76Trf_OptionVectors*
77TrfBZ2Options ()
78{
79  static Trf_OptionVectors optVec = /* THREADING: constant, read-only => safe */
80    {
81      CreateOptions,
82      DeleteOptions,
83      CheckOptions,
84      NULL,      /* no string procedure for 'SetOption' */
85      SetOption,
86      QueryOptions,
87      NULL       /* unseekable, unchanged by options */
88    };
89
90  return &optVec;
91}
92
93/*
94 *------------------------------------------------------*
95 *
96 *	CreateOptions --
97 *
98 *	------------------------------------------------*
99 *	Create option structure for ZIP transformations.
100 *	------------------------------------------------*
101 *
102 *	Sideeffects:
103 *		Allocates memory and initializes it as
104 *		option structure for ZIP
105 *		transformations.
106 *
107 *	Result:
108 *		A reference to the allocated block of
109 *		memory.
110 *
111 *------------------------------------------------------*
112 */
113
114static Trf_Options
115CreateOptions (clientData)
116ClientData clientData;
117{
118  TrfZipOptionBlock* o;
119
120  o = (TrfZipOptionBlock*) ckalloc (sizeof (TrfZipOptionBlock));
121
122  o->mode  = TRF_UNKNOWN_MODE;
123  o->level = 9;
124
125  return (Trf_Options) o;
126}
127
128/*
129 *------------------------------------------------------*
130 *
131 *	DeleteOptions --
132 *
133 *	------------------------------------------------*
134 *	Delete option structure of a ZIP transformations
135 *	------------------------------------------------*
136 *
137 *	Sideeffects:
138 *		A memory block allocated by 'CreateOptions'
139 *		is released.
140 *
141 *	Result:
142 *		None.
143 *
144 *------------------------------------------------------*
145 */
146
147static void
148DeleteOptions (options, clientData)
149Trf_Options options;
150ClientData  clientData;
151{
152  ckfree ((VOID*) options);
153}
154
155/*
156 *------------------------------------------------------*
157 *
158 *	CheckOptions --
159 *
160 *	------------------------------------------------*
161 *	Check the given option structure for errors.
162 *	------------------------------------------------*
163 *
164 *	Sideeffects:
165 *		May modify the given structure to set
166 *		default values into uninitialized parts.
167 *
168 *	Result:
169 *		A standard Tcl error code.
170 *
171 *------------------------------------------------------*
172 */
173
174static int
175CheckOptions (options, interp, baseOptions, clientData)
176Trf_Options            options;
177Tcl_Interp*            interp;
178CONST Trf_BaseOptions* baseOptions;
179ClientData             clientData;
180{
181  TrfZipOptionBlock* o = (TrfZipOptionBlock*) options;
182
183  /*
184   * 'bz2' is used, therefore load the required library.
185   * And bail out if it is not available.
186   */
187
188  if (TCL_OK != TrfLoadBZ2lib (interp)) {
189    return TCL_ERROR;
190  }
191
192  /*
193   * Now perform the real option check.
194   */
195
196  if (baseOptions->attach == (Tcl_Channel) NULL) /* IMMEDIATE? */ {
197    if (o->mode == TRF_UNKNOWN_MODE) {
198      Tcl_AppendResult (interp, "-mode option not set", (char*) NULL);
199      return TCL_ERROR;
200    }
201  } else /* ATTACH */ {
202    if (o->mode == TRF_UNKNOWN_MODE) {
203      o->mode = TRF_COMPRESS;
204    }
205  }
206
207  return TCL_OK;
208}
209
210/*
211 *------------------------------------------------------*
212 *
213 *	SetOption --
214 *
215 *	------------------------------------------------*
216 *	Define value of given option.
217 *	------------------------------------------------*
218 *
219 *	Sideeffects:
220 *		Sets the given value into the option
221 *		structure
222 *
223 *	Result:
224 *		A standard Tcl error code.
225 *
226 *------------------------------------------------------*
227 */
228
229static int
230SetOption (options, interp, optname, optvalue, clientData)
231Trf_Options options;
232Tcl_Interp* interp;
233CONST char* optname;
234CONST Tcl_Obj* optvalue;
235ClientData  clientData;
236{
237  /* Possible options:
238   *
239   * -level <number>
240   * -level default
241   * -mode compress|decompress
242   */
243
244  TrfZipOptionBlock* o = (TrfZipOptionBlock*) options;
245  int              len = strlen (optname + 1);
246  CONST char*      value;
247
248  switch (optname [1]) {
249  case 'l':
250    if (0 != strncmp (optname, "-level", len))
251      goto unknown_option;
252
253    value = Tcl_GetStringFromObj ((Tcl_Obj*) optvalue, NULL);
254    len = strlen (value);
255
256    if (0 == strncmp (value, "default", len)) {
257      o->level = 9;
258    } else {
259      int res, val;
260
261      int v;
262      res = Tcl_GetIntFromObj (interp, (Tcl_Obj*) optvalue, &v);
263      val = v;
264
265      if (res != TCL_OK) {
266	return res;
267      }
268
269      if ((val < TRF_MIN_LEVEL) || (val > TRF_MAX_LEVEL)) {
270	Tcl_AppendResult (interp, "level out of range ", (char*) NULL);
271	Tcl_AppendResult (interp, TRF_MIN_LEVEL_STR, (char*) NULL);
272	Tcl_AppendResult (interp, "..", (char*) NULL);
273	Tcl_AppendResult (interp, TRF_MAX_LEVEL_STR, (char*) NULL);
274	return TCL_ERROR;
275      }
276
277      o->level = val;
278    }
279    break;
280
281  case 'm':
282    if (0 != strncmp (optname, "-mode", len))
283      goto unknown_option;
284
285    value = Tcl_GetStringFromObj ((Tcl_Obj*) optvalue, NULL);
286    len   = strlen (value);
287
288    switch (value [0]) {
289    case 'c':
290      if (0 != strncmp (value, "compress", len))
291	goto unknown_mode;
292
293      o->mode = TRF_COMPRESS;
294      break;
295
296    case 'd':
297      if (0 != strncmp (value, "decompress", len))
298	goto unknown_mode;
299
300      o->mode = TRF_DECOMPRESS;
301      break;
302
303    default:
304    unknown_mode:
305      Tcl_AppendResult (interp, "unknown mode '", (char*) NULL);
306      Tcl_AppendResult (interp, value, (char*) NULL);
307      Tcl_AppendResult (interp, "', should be 'compress' or 'decompress'", (char*) NULL);
308      return TCL_ERROR;
309      break;
310    } /* switch optvalue */
311    break;
312
313  default:
314    goto unknown_option;
315    break;
316  }
317
318  return TCL_OK;
319
320 unknown_option:
321  Tcl_AppendResult (interp, "unknown option '", (char*) NULL);
322  Tcl_AppendResult (interp, optname, (char*) NULL);
323  Tcl_AppendResult (interp, "', should be '-level' or '-mode'", (char*) NULL);
324  return TCL_ERROR;
325}
326
327/*
328 *------------------------------------------------------*
329 *
330 *	QueryOptions --
331 *
332 *	------------------------------------------------*
333 *	Returns a value indicating wether the encoder or
334 *	decoder set of vectors is to be used by immediate
335 *	execution.
336 *	------------------------------------------------*
337 *
338 *	Sideeffects:
339 *		None
340 *
341 *	Result:
342 *		1 - use encoder vectors.
343 *		0 - use decoder vectors.
344 *
345 *------------------------------------------------------*
346 */
347
348static int
349QueryOptions (options, clientData)
350Trf_Options options;
351ClientData  clientData;
352{
353  TrfZipOptionBlock* o = (TrfZipOptionBlock*) options;
354
355  return (o->mode == TRF_COMPRESS ? 1 : 0);
356}
357
358