symbian-qemu-0.9.1-12/zlib-1.2.3/example.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* example.c -- usage example of the zlib compression library
       
     2  * Copyright (C) 1995-2004 Jean-loup Gailly.
       
     3  * For conditions of distribution and use, see copyright notice in zlib.h
       
     4  */
       
     5 
       
     6 /* @(#) $Id$ */
       
     7 
       
     8 #include <stdio.h>
       
     9 #include "zlib.h"
       
    10 
       
    11 #ifdef STDC
       
    12 #  include <string.h>
       
    13 #  include <stdlib.h>
       
    14 #endif
       
    15 
       
    16 #if defined(VMS) || defined(RISCOS)
       
    17 #  define TESTFILE "foo-gz"
       
    18 #else
       
    19 #  define TESTFILE "foo.gz"
       
    20 #endif
       
    21 
       
    22 #define CHECK_ERR(err, msg) { \
       
    23     if (err != Z_OK) { \
       
    24         fprintf(stderr, "%s error: %d\n", msg, err); \
       
    25         exit(1); \
       
    26     } \
       
    27 }
       
    28 
       
    29 const char hello[] = "hello, hello!";
       
    30 /* "hello world" would be more standard, but the repeated "hello"
       
    31  * stresses the compression code better, sorry...
       
    32  */
       
    33 
       
    34 const char dictionary[] = "hello";
       
    35 uLong dictId; /* Adler32 value of the dictionary */
       
    36 
       
    37 void test_compress      OF((Byte *compr, uLong comprLen,
       
    38                             Byte *uncompr, uLong uncomprLen));
       
    39 void test_gzio          OF((const char *fname,
       
    40                             Byte *uncompr, uLong uncomprLen));
       
    41 void test_deflate       OF((Byte *compr, uLong comprLen));
       
    42 void test_inflate       OF((Byte *compr, uLong comprLen,
       
    43                             Byte *uncompr, uLong uncomprLen));
       
    44 void test_large_deflate OF((Byte *compr, uLong comprLen,
       
    45                             Byte *uncompr, uLong uncomprLen));
       
    46 void test_large_inflate OF((Byte *compr, uLong comprLen,
       
    47                             Byte *uncompr, uLong uncomprLen));
       
    48 void test_flush         OF((Byte *compr, uLong *comprLen));
       
    49 void test_sync          OF((Byte *compr, uLong comprLen,
       
    50                             Byte *uncompr, uLong uncomprLen));
       
    51 void test_dict_deflate  OF((Byte *compr, uLong comprLen));
       
    52 void test_dict_inflate  OF((Byte *compr, uLong comprLen,
       
    53                             Byte *uncompr, uLong uncomprLen));
       
    54 int  main               OF((int argc, char *argv[]));
       
    55 
       
    56 /* ===========================================================================
       
    57  * Test compress() and uncompress()
       
    58  */
       
    59 void test_compress(compr, comprLen, uncompr, uncomprLen)
       
    60     Byte *compr, *uncompr;
       
    61     uLong comprLen, uncomprLen;
       
    62 {
       
    63     int err;
       
    64     uLong len = (uLong)strlen(hello)+1;
       
    65 
       
    66     err = compress(compr, &comprLen, (const Bytef*)hello, len);
       
    67     CHECK_ERR(err, "compress");
       
    68 
       
    69     strcpy((char*)uncompr, "garbage");
       
    70 
       
    71     err = uncompress(uncompr, &uncomprLen, compr, comprLen);
       
    72     CHECK_ERR(err, "uncompress");
       
    73 
       
    74     if (strcmp((char*)uncompr, hello)) {
       
    75         fprintf(stderr, "bad uncompress\n");
       
    76         exit(1);
       
    77     } else {
       
    78         printf("uncompress(): %s\n", (char *)uncompr);
       
    79     }
       
    80 }
       
    81 
       
    82 /* ===========================================================================
       
    83  * Test read/write of .gz files
       
    84  */
       
    85 void test_gzio(fname, uncompr, uncomprLen)
       
    86     const char *fname; /* compressed file name */
       
    87     Byte *uncompr;
       
    88     uLong uncomprLen;
       
    89 {
       
    90 #ifdef NO_GZCOMPRESS
       
    91     fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
       
    92 #else
       
    93     int err;
       
    94     int len = (int)strlen(hello)+1;
       
    95     gzFile file;
       
    96     z_off_t pos;
       
    97 
       
    98     file = gzopen(fname, "wb");
       
    99     if (file == NULL) {
       
   100         fprintf(stderr, "gzopen error\n");
       
   101         exit(1);
       
   102     }
       
   103     gzputc(file, 'h');
       
   104     if (gzputs(file, "ello") != 4) {
       
   105         fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
       
   106         exit(1);
       
   107     }
       
   108     if (gzprintf(file, ", %s!", "hello") != 8) {
       
   109         fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
       
   110         exit(1);
       
   111     }
       
   112     gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
       
   113     gzclose(file);
       
   114 
       
   115     file = gzopen(fname, "rb");
       
   116     if (file == NULL) {
       
   117         fprintf(stderr, "gzopen error\n");
       
   118         exit(1);
       
   119     }
       
   120     strcpy((char*)uncompr, "garbage");
       
   121 
       
   122     if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
       
   123         fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
       
   124         exit(1);
       
   125     }
       
   126     if (strcmp((char*)uncompr, hello)) {
       
   127         fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
       
   128         exit(1);
       
   129     } else {
       
   130         printf("gzread(): %s\n", (char*)uncompr);
       
   131     }
       
   132 
       
   133     pos = gzseek(file, -8L, SEEK_CUR);
       
   134     if (pos != 6 || gztell(file) != pos) {
       
   135         fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
       
   136                 (long)pos, (long)gztell(file));
       
   137         exit(1);
       
   138     }
       
   139 
       
   140     if (gzgetc(file) != ' ') {
       
   141         fprintf(stderr, "gzgetc error\n");
       
   142         exit(1);
       
   143     }
       
   144 
       
   145     if (gzungetc(' ', file) != ' ') {
       
   146         fprintf(stderr, "gzungetc error\n");
       
   147         exit(1);
       
   148     }
       
   149 
       
   150     gzgets(file, (char*)uncompr, (int)uncomprLen);
       
   151     if (strlen((char*)uncompr) != 7) { /* " hello!" */
       
   152         fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
       
   153         exit(1);
       
   154     }
       
   155     if (strcmp((char*)uncompr, hello + 6)) {
       
   156         fprintf(stderr, "bad gzgets after gzseek\n");
       
   157         exit(1);
       
   158     } else {
       
   159         printf("gzgets() after gzseek: %s\n", (char*)uncompr);
       
   160     }
       
   161 
       
   162     gzclose(file);
       
   163 #endif
       
   164 }
       
   165 
       
   166 /* ===========================================================================
       
   167  * Test deflate() with small buffers
       
   168  */
       
   169 void test_deflate(compr, comprLen)
       
   170     Byte *compr;
       
   171     uLong comprLen;
       
   172 {
       
   173     z_stream c_stream; /* compression stream */
       
   174     int err;
       
   175     uLong len = (uLong)strlen(hello)+1;
       
   176 
       
   177     c_stream.zalloc = (alloc_func)0;
       
   178     c_stream.zfree = (free_func)0;
       
   179     c_stream.opaque = (voidpf)0;
       
   180 
       
   181     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
       
   182     CHECK_ERR(err, "deflateInit");
       
   183 
       
   184     c_stream.next_in  = (Bytef*)hello;
       
   185     c_stream.next_out = compr;
       
   186 
       
   187     while (c_stream.total_in != len && c_stream.total_out < comprLen) {
       
   188         c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
       
   189         err = deflate(&c_stream, Z_NO_FLUSH);
       
   190         CHECK_ERR(err, "deflate");
       
   191     }
       
   192     /* Finish the stream, still forcing small buffers: */
       
   193     for (;;) {
       
   194         c_stream.avail_out = 1;
       
   195         err = deflate(&c_stream, Z_FINISH);
       
   196         if (err == Z_STREAM_END) break;
       
   197         CHECK_ERR(err, "deflate");
       
   198     }
       
   199 
       
   200     err = deflateEnd(&c_stream);
       
   201     CHECK_ERR(err, "deflateEnd");
       
   202 }
       
   203 
       
   204 /* ===========================================================================
       
   205  * Test inflate() with small buffers
       
   206  */
       
   207 void test_inflate(compr, comprLen, uncompr, uncomprLen)
       
   208     Byte *compr, *uncompr;
       
   209     uLong comprLen, uncomprLen;
       
   210 {
       
   211     int err;
       
   212     z_stream d_stream; /* decompression stream */
       
   213 
       
   214     strcpy((char*)uncompr, "garbage");
       
   215 
       
   216     d_stream.zalloc = (alloc_func)0;
       
   217     d_stream.zfree = (free_func)0;
       
   218     d_stream.opaque = (voidpf)0;
       
   219 
       
   220     d_stream.next_in  = compr;
       
   221     d_stream.avail_in = 0;
       
   222     d_stream.next_out = uncompr;
       
   223 
       
   224     err = inflateInit(&d_stream);
       
   225     CHECK_ERR(err, "inflateInit");
       
   226 
       
   227     while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
       
   228         d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
       
   229         err = inflate(&d_stream, Z_NO_FLUSH);
       
   230         if (err == Z_STREAM_END) break;
       
   231         CHECK_ERR(err, "inflate");
       
   232     }
       
   233 
       
   234     err = inflateEnd(&d_stream);
       
   235     CHECK_ERR(err, "inflateEnd");
       
   236 
       
   237     if (strcmp((char*)uncompr, hello)) {
       
   238         fprintf(stderr, "bad inflate\n");
       
   239         exit(1);
       
   240     } else {
       
   241         printf("inflate(): %s\n", (char *)uncompr);
       
   242     }
       
   243 }
       
   244 
       
   245 /* ===========================================================================
       
   246  * Test deflate() with large buffers and dynamic change of compression level
       
   247  */
       
   248 void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
       
   249     Byte *compr, *uncompr;
       
   250     uLong comprLen, uncomprLen;
       
   251 {
       
   252     z_stream c_stream; /* compression stream */
       
   253     int err;
       
   254 
       
   255     c_stream.zalloc = (alloc_func)0;
       
   256     c_stream.zfree = (free_func)0;
       
   257     c_stream.opaque = (voidpf)0;
       
   258 
       
   259     err = deflateInit(&c_stream, Z_BEST_SPEED);
       
   260     CHECK_ERR(err, "deflateInit");
       
   261 
       
   262     c_stream.next_out = compr;
       
   263     c_stream.avail_out = (uInt)comprLen;
       
   264 
       
   265     /* At this point, uncompr is still mostly zeroes, so it should compress
       
   266      * very well:
       
   267      */
       
   268     c_stream.next_in = uncompr;
       
   269     c_stream.avail_in = (uInt)uncomprLen;
       
   270     err = deflate(&c_stream, Z_NO_FLUSH);
       
   271     CHECK_ERR(err, "deflate");
       
   272     if (c_stream.avail_in != 0) {
       
   273         fprintf(stderr, "deflate not greedy\n");
       
   274         exit(1);
       
   275     }
       
   276 
       
   277     /* Feed in already compressed data and switch to no compression: */
       
   278     deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
       
   279     c_stream.next_in = compr;
       
   280     c_stream.avail_in = (uInt)comprLen/2;
       
   281     err = deflate(&c_stream, Z_NO_FLUSH);
       
   282     CHECK_ERR(err, "deflate");
       
   283 
       
   284     /* Switch back to compressing mode: */
       
   285     deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
       
   286     c_stream.next_in = uncompr;
       
   287     c_stream.avail_in = (uInt)uncomprLen;
       
   288     err = deflate(&c_stream, Z_NO_FLUSH);
       
   289     CHECK_ERR(err, "deflate");
       
   290 
       
   291     err = deflate(&c_stream, Z_FINISH);
       
   292     if (err != Z_STREAM_END) {
       
   293         fprintf(stderr, "deflate should report Z_STREAM_END\n");
       
   294         exit(1);
       
   295     }
       
   296     err = deflateEnd(&c_stream);
       
   297     CHECK_ERR(err, "deflateEnd");
       
   298 }
       
   299 
       
   300 /* ===========================================================================
       
   301  * Test inflate() with large buffers
       
   302  */
       
   303 void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
       
   304     Byte *compr, *uncompr;
       
   305     uLong comprLen, uncomprLen;
       
   306 {
       
   307     int err;
       
   308     z_stream d_stream; /* decompression stream */
       
   309 
       
   310     strcpy((char*)uncompr, "garbage");
       
   311 
       
   312     d_stream.zalloc = (alloc_func)0;
       
   313     d_stream.zfree = (free_func)0;
       
   314     d_stream.opaque = (voidpf)0;
       
   315 
       
   316     d_stream.next_in  = compr;
       
   317     d_stream.avail_in = (uInt)comprLen;
       
   318 
       
   319     err = inflateInit(&d_stream);
       
   320     CHECK_ERR(err, "inflateInit");
       
   321 
       
   322     for (;;) {
       
   323         d_stream.next_out = uncompr;            /* discard the output */
       
   324         d_stream.avail_out = (uInt)uncomprLen;
       
   325         err = inflate(&d_stream, Z_NO_FLUSH);
       
   326         if (err == Z_STREAM_END) break;
       
   327         CHECK_ERR(err, "large inflate");
       
   328     }
       
   329 
       
   330     err = inflateEnd(&d_stream);
       
   331     CHECK_ERR(err, "inflateEnd");
       
   332 
       
   333     if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
       
   334         fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
       
   335         exit(1);
       
   336     } else {
       
   337         printf("large_inflate(): OK\n");
       
   338     }
       
   339 }
       
   340 
       
   341 /* ===========================================================================
       
   342  * Test deflate() with full flush
       
   343  */
       
   344 void test_flush(compr, comprLen)
       
   345     Byte *compr;
       
   346     uLong *comprLen;
       
   347 {
       
   348     z_stream c_stream; /* compression stream */
       
   349     int err;
       
   350     uInt len = (uInt)strlen(hello)+1;
       
   351 
       
   352     c_stream.zalloc = (alloc_func)0;
       
   353     c_stream.zfree = (free_func)0;
       
   354     c_stream.opaque = (voidpf)0;
       
   355 
       
   356     err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
       
   357     CHECK_ERR(err, "deflateInit");
       
   358 
       
   359     c_stream.next_in  = (Bytef*)hello;
       
   360     c_stream.next_out = compr;
       
   361     c_stream.avail_in = 3;
       
   362     c_stream.avail_out = (uInt)*comprLen;
       
   363     err = deflate(&c_stream, Z_FULL_FLUSH);
       
   364     CHECK_ERR(err, "deflate");
       
   365 
       
   366     compr[3]++; /* force an error in first compressed block */
       
   367     c_stream.avail_in = len - 3;
       
   368 
       
   369     err = deflate(&c_stream, Z_FINISH);
       
   370     if (err != Z_STREAM_END) {
       
   371         CHECK_ERR(err, "deflate");
       
   372     }
       
   373     err = deflateEnd(&c_stream);
       
   374     CHECK_ERR(err, "deflateEnd");
       
   375 
       
   376     *comprLen = c_stream.total_out;
       
   377 }
       
   378 
       
   379 /* ===========================================================================
       
   380  * Test inflateSync()
       
   381  */
       
   382 void test_sync(compr, comprLen, uncompr, uncomprLen)
       
   383     Byte *compr, *uncompr;
       
   384     uLong comprLen, uncomprLen;
       
   385 {
       
   386     int err;
       
   387     z_stream d_stream; /* decompression stream */
       
   388 
       
   389     strcpy((char*)uncompr, "garbage");
       
   390 
       
   391     d_stream.zalloc = (alloc_func)0;
       
   392     d_stream.zfree = (free_func)0;
       
   393     d_stream.opaque = (voidpf)0;
       
   394 
       
   395     d_stream.next_in  = compr;
       
   396     d_stream.avail_in = 2; /* just read the zlib header */
       
   397 
       
   398     err = inflateInit(&d_stream);
       
   399     CHECK_ERR(err, "inflateInit");
       
   400 
       
   401     d_stream.next_out = uncompr;
       
   402     d_stream.avail_out = (uInt)uncomprLen;
       
   403 
       
   404     inflate(&d_stream, Z_NO_FLUSH);
       
   405     CHECK_ERR(err, "inflate");
       
   406 
       
   407     d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
       
   408     err = inflateSync(&d_stream);           /* but skip the damaged part */
       
   409     CHECK_ERR(err, "inflateSync");
       
   410 
       
   411     err = inflate(&d_stream, Z_FINISH);
       
   412     if (err != Z_DATA_ERROR) {
       
   413         fprintf(stderr, "inflate should report DATA_ERROR\n");
       
   414         /* Because of incorrect adler32 */
       
   415         exit(1);
       
   416     }
       
   417     err = inflateEnd(&d_stream);
       
   418     CHECK_ERR(err, "inflateEnd");
       
   419 
       
   420     printf("after inflateSync(): hel%s\n", (char *)uncompr);
       
   421 }
       
   422 
       
   423 /* ===========================================================================
       
   424  * Test deflate() with preset dictionary
       
   425  */
       
   426 void test_dict_deflate(compr, comprLen)
       
   427     Byte *compr;
       
   428     uLong comprLen;
       
   429 {
       
   430     z_stream c_stream; /* compression stream */
       
   431     int err;
       
   432 
       
   433     c_stream.zalloc = (alloc_func)0;
       
   434     c_stream.zfree = (free_func)0;
       
   435     c_stream.opaque = (voidpf)0;
       
   436 
       
   437     err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
       
   438     CHECK_ERR(err, "deflateInit");
       
   439 
       
   440     err = deflateSetDictionary(&c_stream,
       
   441                                (const Bytef*)dictionary, sizeof(dictionary));
       
   442     CHECK_ERR(err, "deflateSetDictionary");
       
   443 
       
   444     dictId = c_stream.adler;
       
   445     c_stream.next_out = compr;
       
   446     c_stream.avail_out = (uInt)comprLen;
       
   447 
       
   448     c_stream.next_in = (Bytef*)hello;
       
   449     c_stream.avail_in = (uInt)strlen(hello)+1;
       
   450 
       
   451     err = deflate(&c_stream, Z_FINISH);
       
   452     if (err != Z_STREAM_END) {
       
   453         fprintf(stderr, "deflate should report Z_STREAM_END\n");
       
   454         exit(1);
       
   455     }
       
   456     err = deflateEnd(&c_stream);
       
   457     CHECK_ERR(err, "deflateEnd");
       
   458 }
       
   459 
       
   460 /* ===========================================================================
       
   461  * Test inflate() with a preset dictionary
       
   462  */
       
   463 void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
       
   464     Byte *compr, *uncompr;
       
   465     uLong comprLen, uncomprLen;
       
   466 {
       
   467     int err;
       
   468     z_stream d_stream; /* decompression stream */
       
   469 
       
   470     strcpy((char*)uncompr, "garbage");
       
   471 
       
   472     d_stream.zalloc = (alloc_func)0;
       
   473     d_stream.zfree = (free_func)0;
       
   474     d_stream.opaque = (voidpf)0;
       
   475 
       
   476     d_stream.next_in  = compr;
       
   477     d_stream.avail_in = (uInt)comprLen;
       
   478 
       
   479     err = inflateInit(&d_stream);
       
   480     CHECK_ERR(err, "inflateInit");
       
   481 
       
   482     d_stream.next_out = uncompr;
       
   483     d_stream.avail_out = (uInt)uncomprLen;
       
   484 
       
   485     for (;;) {
       
   486         err = inflate(&d_stream, Z_NO_FLUSH);
       
   487         if (err == Z_STREAM_END) break;
       
   488         if (err == Z_NEED_DICT) {
       
   489             if (d_stream.adler != dictId) {
       
   490                 fprintf(stderr, "unexpected dictionary");
       
   491                 exit(1);
       
   492             }
       
   493             err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
       
   494                                        sizeof(dictionary));
       
   495         }
       
   496         CHECK_ERR(err, "inflate with dict");
       
   497     }
       
   498 
       
   499     err = inflateEnd(&d_stream);
       
   500     CHECK_ERR(err, "inflateEnd");
       
   501 
       
   502     if (strcmp((char*)uncompr, hello)) {
       
   503         fprintf(stderr, "bad inflate with dict\n");
       
   504         exit(1);
       
   505     } else {
       
   506         printf("inflate with dictionary: %s\n", (char *)uncompr);
       
   507     }
       
   508 }
       
   509 
       
   510 /* ===========================================================================
       
   511  * Usage:  example [output.gz  [input.gz]]
       
   512  */
       
   513 
       
   514 int main(argc, argv)
       
   515     int argc;
       
   516     char *argv[];
       
   517 {
       
   518     Byte *compr, *uncompr;
       
   519     uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
       
   520     uLong uncomprLen = comprLen;
       
   521     static const char* myVersion = ZLIB_VERSION;
       
   522 
       
   523     if (zlibVersion()[0] != myVersion[0]) {
       
   524         fprintf(stderr, "incompatible zlib version\n");
       
   525         exit(1);
       
   526 
       
   527     } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
       
   528         fprintf(stderr, "warning: different zlib version\n");
       
   529     }
       
   530 
       
   531     printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
       
   532             ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
       
   533 
       
   534     compr    = (Byte*)calloc((uInt)comprLen, 1);
       
   535     uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
       
   536     /* compr and uncompr are cleared to avoid reading uninitialized
       
   537      * data and to ensure that uncompr compresses well.
       
   538      */
       
   539     if (compr == Z_NULL || uncompr == Z_NULL) {
       
   540         printf("out of memory\n");
       
   541         exit(1);
       
   542     }
       
   543     test_compress(compr, comprLen, uncompr, uncomprLen);
       
   544 
       
   545     test_gzio((argc > 1 ? argv[1] : TESTFILE),
       
   546               uncompr, uncomprLen);
       
   547 
       
   548     test_deflate(compr, comprLen);
       
   549     test_inflate(compr, comprLen, uncompr, uncomprLen);
       
   550 
       
   551     test_large_deflate(compr, comprLen, uncompr, uncomprLen);
       
   552     test_large_inflate(compr, comprLen, uncompr, uncomprLen);
       
   553 
       
   554     test_flush(compr, &comprLen);
       
   555     test_sync(compr, comprLen, uncompr, uncomprLen);
       
   556     comprLen = uncomprLen;
       
   557 
       
   558     test_dict_deflate(compr, comprLen);
       
   559     test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
       
   560 
       
   561     free(compr);
       
   562     free(uncompr);
       
   563 
       
   564     return 0;
       
   565 }