root/maint/gnulib/tests/test-striconveh.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. new_offsets
  2. main

   1 /* Test of character set conversion with error handling.
   2    Copyright (C) 2007-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
  18 
  19 #include <config.h>
  20 
  21 #include "striconveh.h"
  22 
  23 #if HAVE_ICONV
  24 # include <iconv.h>
  25 #endif
  26 
  27 #include <errno.h>
  28 #include <stdlib.h>
  29 #include <string.h>
  30 
  31 #include "macros.h"
  32 
  33 /* Magic number for detecting bounds violations.  */
  34 #define MAGIC 0x1983EFF1
  35 
  36 static size_t *
  37 new_offsets (size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39   size_t *offsets = (size_t *) malloc ((n + 1) * sizeof (size_t));
  40   offsets[n] = MAGIC;
  41   return offsets;
  42 }
  43 
  44 int
  45 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47 #if HAVE_ICONV
  48   static enum iconv_ilseq_handler handlers[] =
  49     { iconveh_error, iconveh_question_mark, iconveh_escape_sequence };
  50   size_t indirect;
  51   size_t h;
  52   size_t o;
  53   size_t i;
  54 
  55   /* Assume that iconv() supports at least the encodings ASCII, ISO-8859-1,
  56      ISO-8859-2, and UTF-8.  */
  57   iconv_t cd_ascii_to_88591 = iconv_open ("ISO-8859-1", "ASCII");
  58   iconv_t cd_88591_to_88592 = iconv_open ("ISO-8859-2", "ISO-8859-1");
  59   iconv_t cd_88592_to_88591 = iconv_open ("ISO-8859-1", "ISO-8859-2");
  60   iconv_t cd_ascii_to_utf8 = iconv_open ("UTF-8", "ASCII");
  61   iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
  62   iconv_t cd_utf8_to_88591 = iconv_open ("ISO-8859-1", "UTF-8");
  63   iconv_t cd_88592_to_utf8 = iconv_open ("UTF-8", "ISO-8859-2");
  64   iconv_t cd_utf8_to_88592 = iconv_open ("ISO-8859-2", "UTF-8");
  65   iconv_t cd_utf7_to_utf8 = iconv_open ("UTF-8", "UTF-7");
  66   iconveh_t cdeh_ascii_to_88591;
  67   iconveh_t cdeh_ascii_to_88591_indirectly;
  68   iconveh_t cdeh_88592_to_88591;
  69   iconveh_t cdeh_88592_to_88591_indirectly;
  70   iconveh_t cdeh_ascii_to_utf8;
  71   iconveh_t cdeh_88591_to_utf8;
  72   iconveh_t cdeh_utf8_to_88591;
  73   iconveh_t cdeh_utf7_to_utf8;
  74 
  75   ASSERT (cd_ascii_to_utf8 != (iconv_t)(-1));
  76   ASSERT (cd_88591_to_utf8 != (iconv_t)(-1));
  77   ASSERT (cd_utf8_to_88591 != (iconv_t)(-1));
  78   ASSERT (cd_88592_to_utf8 != (iconv_t)(-1));
  79   ASSERT (cd_utf8_to_88592 != (iconv_t)(-1));
  80 
  81   cdeh_ascii_to_88591.cd = cd_ascii_to_88591;
  82   cdeh_ascii_to_88591.cd1 = cd_ascii_to_utf8;
  83   cdeh_ascii_to_88591.cd2 = cd_utf8_to_88591;
  84 
  85   cdeh_ascii_to_88591_indirectly.cd = (iconv_t)(-1);
  86   cdeh_ascii_to_88591_indirectly.cd1 = cd_ascii_to_utf8;
  87   cdeh_ascii_to_88591_indirectly.cd2 = cd_utf8_to_88591;
  88 
  89   cdeh_88592_to_88591.cd = cd_88592_to_88591;
  90   cdeh_88592_to_88591.cd1 = cd_88592_to_utf8;
  91   cdeh_88592_to_88591.cd2 = cd_utf8_to_88591;
  92 
  93   cdeh_88592_to_88591_indirectly.cd = (iconv_t)(-1);
  94   cdeh_88592_to_88591_indirectly.cd1 = cd_88592_to_utf8;
  95   cdeh_88592_to_88591_indirectly.cd2 = cd_utf8_to_88591;
  96 
  97   cdeh_ascii_to_utf8.cd = cd_ascii_to_utf8;
  98   cdeh_ascii_to_utf8.cd1 = cd_ascii_to_utf8;
  99   cdeh_ascii_to_utf8.cd2 = (iconv_t)(-1);
 100 
 101   cdeh_88591_to_utf8.cd = cd_88591_to_utf8;
 102   cdeh_88591_to_utf8.cd1 = cd_88591_to_utf8;
 103   cdeh_88591_to_utf8.cd2 = (iconv_t)(-1);
 104 
 105   cdeh_utf8_to_88591.cd = cd_utf8_to_88591;
 106   cdeh_utf8_to_88591.cd1 = (iconv_t)(-1);
 107   cdeh_utf8_to_88591.cd2 = cd_utf8_to_88591;
 108 
 109   cdeh_utf7_to_utf8.cd = cd_utf7_to_utf8;
 110   cdeh_utf7_to_utf8.cd1 = cd_utf7_to_utf8;
 111   cdeh_utf7_to_utf8.cd2 = (iconv_t)(-1);
 112 
 113   /* ------------------------ Test mem_cd_iconveh() ------------------------ */
 114 
 115   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
 116   for (indirect = 0; indirect <= 1; indirect++)
 117     {
 118       for (h = 0; h < SIZEOF (handlers); h++)
 119         {
 120           enum iconv_ilseq_handler handler = handlers[h];
 121           static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 122           static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 123           for (o = 0; o < 2; o++)
 124             {
 125               size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 126               char *result = NULL;
 127               size_t length = 0;
 128               int retval = mem_cd_iconveh (input, strlen (input),
 129                                            (indirect
 130                                             ? &cdeh_88592_to_88591_indirectly
 131                                             : &cdeh_88592_to_88591),
 132                                            handler,
 133                                            offsets,
 134                                            &result, &length);
 135               ASSERT (retval == 0);
 136               ASSERT (length == strlen (expected));
 137               ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 138               if (o)
 139                 {
 140                   for (i = 0; i < 37; i++)
 141                     ASSERT (offsets[i] == i);
 142                   ASSERT (offsets[37] == MAGIC);
 143                   free (offsets);
 144                 }
 145               free (result);
 146             }
 147         }
 148     }
 149 
 150   /* Test conversion from ASCII to ISO-8859-1 with invalid input (EILSEQ).  */
 151   for (indirect = 0; indirect <= 1; indirect++)
 152     {
 153       for (h = 0; h < SIZEOF (handlers); h++)
 154         {
 155           enum iconv_ilseq_handler handler = handlers[h];
 156           static const char input[] = "Rafa\263 Maszkowski"; /* Rafa? Maszkowski */
 157           for (o = 0; o < 2; o++)
 158             {
 159               size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 160               char *result = NULL;
 161               size_t length = 0;
 162               int retval = mem_cd_iconveh (input, strlen (input),
 163                                            (indirect
 164                                             ? &cdeh_ascii_to_88591_indirectly
 165                                             : &cdeh_ascii_to_88591),
 166                                            handler,
 167                                            offsets,
 168                                            &result, &length);
 169               switch (handler)
 170                 {
 171                 case iconveh_error:
 172                   ASSERT (retval == -1 && errno == EILSEQ);
 173                   ASSERT (result == NULL);
 174                   if (o)
 175                     free (offsets);
 176                   break;
 177                 case iconveh_question_mark:
 178                 case iconveh_escape_sequence:
 179                   {
 180                     static const char expected[] = "Rafa? Maszkowski";
 181                     ASSERT (retval == 0);
 182                     ASSERT (length == strlen (expected));
 183                     ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 184                     if (o)
 185                       {
 186                         for (i = 0; i < 16; i++)
 187                           ASSERT (offsets[i] == i);
 188                         ASSERT (offsets[16] == MAGIC);
 189                         free (offsets);
 190                       }
 191                     free (result);
 192                   }
 193                   break;
 194                 }
 195             }
 196         }
 197     }
 198 
 199   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
 200   for (indirect = 0; indirect <= 1; indirect++)
 201     {
 202       for (h = 0; h < SIZEOF (handlers); h++)
 203         {
 204           enum iconv_ilseq_handler handler = handlers[h];
 205           static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
 206           for (o = 0; o < 2; o++)
 207             {
 208               size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 209               char *result = NULL;
 210               size_t length = 0;
 211               int retval = mem_cd_iconveh (input, strlen (input),
 212                                            (indirect
 213                                             ? &cdeh_88592_to_88591_indirectly
 214                                             : &cdeh_88592_to_88591),
 215                                            handler,
 216                                            offsets,
 217                                            &result, &length);
 218               switch (handler)
 219                 {
 220                 case iconveh_error:
 221                   ASSERT (retval == -1 && errno == EILSEQ);
 222                   ASSERT (result == NULL);
 223                   if (o)
 224                     free (offsets);
 225                   break;
 226                 case iconveh_question_mark:
 227                   {
 228                     static const char expected[] = "Rafa? Maszkowski";
 229                     ASSERT (retval == 0);
 230                     ASSERT (length == strlen (expected));
 231                     ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 232                     if (o)
 233                       {
 234                         for (i = 0; i < 16; i++)
 235                           ASSERT (offsets[i] == i);
 236                         ASSERT (offsets[16] == MAGIC);
 237                         free (offsets);
 238                       }
 239                     free (result);
 240                   }
 241                   break;
 242                 case iconveh_escape_sequence:
 243                   {
 244                     static const char expected[] = "Rafa\\u0142 Maszkowski";
 245                     ASSERT (retval == 0);
 246                     ASSERT (length == strlen (expected));
 247                     ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 248                     if (o)
 249                       {
 250                         for (i = 0; i < 16; i++)
 251                           ASSERT (offsets[i] == (i < 5 ? i :
 252                                                  i + 5));
 253                         ASSERT (offsets[16] == MAGIC);
 254                         free (offsets);
 255                       }
 256                     free (result);
 257                   }
 258                   break;
 259                 }
 260             }
 261         }
 262     }
 263 
 264   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
 265   for (h = 0; h < SIZEOF (handlers); h++)
 266     {
 267       enum iconv_ilseq_handler handler = handlers[h];
 268       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 269       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
 270       for (o = 0; o < 2; o++)
 271         {
 272           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 273           char *result = NULL;
 274           size_t length = 0;
 275           int retval = mem_cd_iconveh (input, strlen (input),
 276                                        &cdeh_88591_to_utf8,
 277                                        handler,
 278                                        offsets,
 279                                        &result, &length);
 280           ASSERT (retval == 0);
 281           ASSERT (length == strlen (expected));
 282           ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 283           if (o)
 284             {
 285               for (i = 0; i < 37; i++)
 286                 ASSERT (offsets[i] == (i < 1 ? i :
 287                                        i < 12 ? i + 1 :
 288                                        i < 18 ? i + 2 :
 289                                        i + 3));
 290               ASSERT (offsets[37] == MAGIC);
 291               free (offsets);
 292             }
 293           free (result);
 294         }
 295     }
 296 
 297   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
 298   for (h = 0; h < SIZEOF (handlers); h++)
 299     {
 300       enum iconv_ilseq_handler handler = handlers[h];
 301       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
 302       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 303       for (o = 0; o < 2; o++)
 304         {
 305           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 306           char *result = NULL;
 307           size_t length = 0;
 308           int retval = mem_cd_iconveh (input, strlen (input),
 309                                        &cdeh_utf8_to_88591,
 310                                        handler,
 311                                        offsets,
 312                                        &result, &length);
 313           ASSERT (retval == 0);
 314           ASSERT (length == strlen (expected));
 315           ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 316           if (o)
 317             {
 318               for (i = 0; i < 41; i++)
 319                 ASSERT (offsets[i] == (i < 1 ? i :
 320                                        i == 1 ? (size_t)(-1) :
 321                                        i < 13 ? i - 1 :
 322                                        i == 13 ? (size_t)(-1) :
 323                                        i < 20 ? i - 2 :
 324                                        i == 20 ? (size_t)(-1) :
 325                                        i < 40 ? i - 3 :
 326                                        (size_t)(-1)));
 327               ASSERT (offsets[41] == MAGIC);
 328               free (offsets);
 329             }
 330           free (result);
 331         }
 332     }
 333 
 334   /* Test conversion from ASCII to UTF-8 with invalid input (EILSEQ).  */
 335   for (h = 0; h < SIZEOF (handlers); h++)
 336     {
 337       enum iconv_ilseq_handler handler = handlers[h];
 338       static const char input[] = "Rafa\263 Maszkowski"; /* Rafa? Maszkowski */
 339       for (o = 0; o < 2; o++)
 340         {
 341           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 342           char *result = NULL;
 343           size_t length = 0;
 344           int retval = mem_cd_iconveh (input, strlen (input),
 345                                        &cdeh_ascii_to_utf8,
 346                                        handler,
 347                                        offsets,
 348                                        &result, &length);
 349           switch (handler)
 350             {
 351             case iconveh_error:
 352               ASSERT (retval == -1 && errno == EILSEQ);
 353               ASSERT (result == NULL);
 354               if (o)
 355                 free (offsets);
 356               break;
 357             case iconveh_question_mark:
 358             case iconveh_escape_sequence:
 359               {
 360                 static const char expected[] = "Rafa? Maszkowski";
 361                 ASSERT (retval == 0);
 362                 ASSERT (length == strlen (expected));
 363                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 364                 if (o)
 365                   {
 366                     for (i = 0; i < 16; i++)
 367                       ASSERT (offsets[i] == i);
 368                     ASSERT (offsets[16] == MAGIC);
 369                     free (offsets);
 370                   }
 371                 free (result);
 372               }
 373               break;
 374             }
 375         }
 376     }
 377 
 378   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
 379   for (h = 0; h < SIZEOF (handlers); h++)
 380     {
 381       enum iconv_ilseq_handler handler = handlers[h];
 382       static const char input[] = "Rafa\305\202 Maszkowski"; /* Rafał Maszkowski */
 383       for (o = 0; o < 2; o++)
 384         {
 385           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 386           char *result = NULL;
 387           size_t length = 0;
 388           int retval = mem_cd_iconveh (input, strlen (input),
 389                                        &cdeh_utf8_to_88591,
 390                                        handler,
 391                                        offsets,
 392                                        &result, &length);
 393           switch (handler)
 394             {
 395             case iconveh_error:
 396               ASSERT (retval == -1 && errno == EILSEQ);
 397               ASSERT (result == NULL);
 398               if (o)
 399                 free (offsets);
 400               break;
 401             case iconveh_question_mark:
 402               {
 403                 static const char expected[] = "Rafa? Maszkowski";
 404                 ASSERT (retval == 0);
 405                 ASSERT (length == strlen (expected));
 406                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 407                 if (o)
 408                   {
 409                     for (i = 0; i < 17; i++)
 410                       ASSERT (offsets[i] == (i < 5 ? i :
 411                                              i == 5 ? (size_t)(-1) :
 412                                              i - 1));
 413                     ASSERT (offsets[17] == MAGIC);
 414                     free (offsets);
 415                   }
 416                 free (result);
 417               }
 418               break;
 419             case iconveh_escape_sequence:
 420               {
 421                 static const char expected[] = "Rafa\\u0142 Maszkowski";
 422                 ASSERT (retval == 0);
 423                 ASSERT (length == strlen (expected));
 424                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 425                 if (o)
 426                   {
 427                     for (i = 0; i < 17; i++)
 428                       ASSERT (offsets[i] == (i < 5 ? i :
 429                                              i == 5 ? (size_t)(-1) :
 430                                              i + 4));
 431                     ASSERT (offsets[17] == MAGIC);
 432                     free (offsets);
 433                   }
 434                 free (result);
 435               }
 436               break;
 437             }
 438         }
 439     }
 440 
 441   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
 442   for (h = 0; h < SIZEOF (handlers); h++)
 443     {
 444       enum iconv_ilseq_handler handler = handlers[h];
 445       static const char input[] = "\342";
 446       for (o = 0; o < 2; o++)
 447         {
 448           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 449           char *result = NULL;
 450           size_t length = 0;
 451           int retval = mem_cd_iconveh (input, strlen (input),
 452                                        &cdeh_utf8_to_88591,
 453                                        handler,
 454                                        offsets,
 455                                        &result, &length);
 456           ASSERT (retval == 0);
 457           ASSERT (length == 0);
 458           if (o)
 459             {
 460               ASSERT (offsets[0] == 0);
 461               ASSERT (offsets[1] == MAGIC);
 462               free (offsets);
 463             }
 464           free (result);
 465         }
 466     }
 467 
 468   if (cd_utf7_to_utf8 != (iconv_t)(-1))
 469     {
 470       /* Disabled on Solaris, because Solaris 9 iconv() is buggy: it returns
 471          -1 / EILSEQ when converting the 7th byte of the input "+VDLYP9hA".  */
 472 # if !(defined __sun && !defined _LIBICONV_VERSION)
 473       /* Test conversion from UTF-7 to UTF-8 with EINVAL.  */
 474       for (h = 0; h < SIZEOF (handlers); h++)
 475         {
 476           enum iconv_ilseq_handler handler = handlers[h];
 477           /* This is base64 encoded 0x54 0x32 0xD8 0x3F 0xD8 0x40.  It would
 478              convert to U+5432 U+D83F U+D840 but these are Unicode surrogates.  */
 479           static const char input[] = "+VDLYP9hA";
 480           static const char expected1[] = "\345\220\262"; /* 吲 glibc */
 481           static const char expected2[] = ""; /* libiconv */
 482           char *result = NULL;
 483           size_t length = 0;
 484           int retval = mem_cd_iconveh (input, 7,
 485                                        &cdeh_utf7_to_utf8,
 486                                        handler,
 487                                        NULL,
 488                                        &result, &length);
 489           ASSERT (retval == 0);
 490           ASSERT (length == strlen (expected1) || length == strlen (expected2));
 491           ASSERT (result != NULL);
 492           if (length == strlen (expected1))
 493             ASSERT (memcmp (result, expected1, strlen (expected1)) == 0);
 494           else
 495             ASSERT (memcmp (result, expected2, strlen (expected2)) == 0);
 496           free (result);
 497         }
 498 
 499       /* Disabled on NetBSD, because NetBSD 5.0 iconv() is buggy: it converts
 500          the input "+2D/YQNhB" to U+1FED8 U+3FD8 U+40D8.  */
 501 #  if !(defined __NetBSD__ && !defined _LIBICONV_VERSION)
 502       /* Test conversion from UTF-7 to UTF-8 with EILSEQ.  */
 503       for (h = 0; h < SIZEOF (handlers); h++)
 504         {
 505           enum iconv_ilseq_handler handler = handlers[h];
 506           /* This is base64 encoded 0xD8 0x3F 0xD8 0x40 0xD8 0x41.  It would
 507              convert to U+D83F U+D840 U+D841 but these are Unicode surrogates.  */
 508           static const char input[] = "+2D/YQNhB";
 509           char *result = NULL;
 510           size_t length = 0;
 511           int retval = mem_cd_iconveh (input, strlen (input),
 512                                        &cdeh_utf7_to_utf8,
 513                                        handler,
 514                                        NULL,
 515                                        &result, &length);
 516           switch (handler)
 517             {
 518             case iconveh_error:
 519               ASSERT (retval == -1 && errno == EILSEQ);
 520               ASSERT (result == NULL);
 521               break;
 522             case iconveh_question_mark:
 523             case iconveh_escape_sequence:
 524               {
 525                 /* glibc result */
 526                 static const char expected1[] = "?????";
 527                 /* libiconv <= 1.12 result */
 528                 static const char expected2[] = "?2D/YQNhB";
 529                 /* libiconv behaviour changed in version 1.13: the result is
 530                    '?' U+0FF6 U+1036; this is U+D83F U+D840 U+D841 shifted left
 531                    by 6 bits.  */
 532                 static const char expected3[] = "?\340\277\266\341\200\266";
 533                 ASSERT (retval == 0);
 534                 ASSERT (length == strlen (expected1)
 535                         || length == strlen (expected2)
 536                         || length == strlen (expected3));
 537                 ASSERT (result != NULL);
 538                 if (length == strlen (expected1))
 539                   ASSERT (memcmp (result, expected1, strlen (expected1)) == 0);
 540                 else if (length == strlen (expected2))
 541                   ASSERT (memcmp (result, expected2, strlen (expected2)) == 0);
 542                 else
 543                   ASSERT (memcmp (result, expected3, strlen (expected3)) == 0);
 544                 free (result);
 545               }
 546               break;
 547             }
 548         }
 549 #  endif
 550 # endif
 551     }
 552 
 553   /* ------------------------ Test str_cd_iconveh() ------------------------ */
 554 
 555   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
 556   for (indirect = 0; indirect <= 1; indirect++)
 557     {
 558       for (h = 0; h < SIZEOF (handlers); h++)
 559         {
 560           enum iconv_ilseq_handler handler = handlers[h];
 561           static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 562           static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 563           char *result = str_cd_iconveh (input,
 564                                          (indirect
 565                                           ? &cdeh_88592_to_88591_indirectly
 566                                           : &cdeh_88592_to_88591),
 567                                          handler);
 568           ASSERT (result != NULL);
 569           ASSERT (strcmp (result, expected) == 0);
 570           free (result);
 571         }
 572     }
 573 
 574   /* Test conversion from ASCII to ISO-8859-1 with invalid input (EILSEQ).  */
 575   for (indirect = 0; indirect <= 1; indirect++)
 576     {
 577       for (h = 0; h < SIZEOF (handlers); h++)
 578         {
 579           enum iconv_ilseq_handler handler = handlers[h];
 580           static const char input[] = "Rafa\263 Maszkowski"; /* Rafa? Maszkowski */
 581           char *result = str_cd_iconveh (input,
 582                                          (indirect
 583                                           ? &cdeh_ascii_to_88591_indirectly
 584                                           : &cdeh_ascii_to_88591),
 585                                          handler);
 586           switch (handler)
 587             {
 588             case iconveh_error:
 589               ASSERT (result == NULL && errno == EILSEQ);
 590               break;
 591             case iconveh_question_mark:
 592             case iconveh_escape_sequence:
 593               {
 594                 static const char expected[] = "Rafa? Maszkowski";
 595                 ASSERT (result != NULL);
 596                 ASSERT (strcmp (result, expected) == 0);
 597                 free (result);
 598               }
 599               break;
 600             }
 601         }
 602     }
 603 
 604   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
 605   for (indirect = 0; indirect <= 1; indirect++)
 606     {
 607       for (h = 0; h < SIZEOF (handlers); h++)
 608         {
 609           enum iconv_ilseq_handler handler = handlers[h];
 610           static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
 611           char *result = str_cd_iconveh (input,
 612                                          (indirect
 613                                           ? &cdeh_88592_to_88591_indirectly
 614                                           : &cdeh_88592_to_88591),
 615                                          handler);
 616           switch (handler)
 617             {
 618             case iconveh_error:
 619               ASSERT (result == NULL && errno == EILSEQ);
 620               break;
 621             case iconveh_question_mark:
 622               {
 623                 static const char expected[] = "Rafa? Maszkowski";
 624                 ASSERT (result != NULL);
 625                 ASSERT (strcmp (result, expected) == 0);
 626                 free (result);
 627               }
 628               break;
 629             case iconveh_escape_sequence:
 630               {
 631                 static const char expected[] = "Rafa\\u0142 Maszkowski";
 632                 ASSERT (result != NULL);
 633                 ASSERT (strcmp (result, expected) == 0);
 634                 free (result);
 635               }
 636               break;
 637             }
 638         }
 639     }
 640 
 641   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
 642   for (h = 0; h < SIZEOF (handlers); h++)
 643     {
 644       enum iconv_ilseq_handler handler = handlers[h];
 645       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 646       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
 647       char *result = str_cd_iconveh (input,
 648                                      &cdeh_88591_to_utf8,
 649                                      handler);
 650       ASSERT (result != NULL);
 651       ASSERT (strcmp (result, expected) == 0);
 652       free (result);
 653     }
 654 
 655   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
 656   for (h = 0; h < SIZEOF (handlers); h++)
 657     {
 658       enum iconv_ilseq_handler handler = handlers[h];
 659       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
 660       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 661       char *result = str_cd_iconveh (input,
 662                                      &cdeh_utf8_to_88591,
 663                                      handler);
 664       ASSERT (result != NULL);
 665       ASSERT (strcmp (result, expected) == 0);
 666       free (result);
 667     }
 668 
 669   /* Test conversion from ASCII to UTF-8 with invalid input (EILSEQ).  */
 670   for (h = 0; h < SIZEOF (handlers); h++)
 671     {
 672       enum iconv_ilseq_handler handler = handlers[h];
 673       static const char input[] = "Rafa\263 Maszkowski"; /* Rafa? Maszkowski */
 674       char *result = str_cd_iconveh (input,
 675                                      &cdeh_ascii_to_utf8,
 676                                      handler);
 677       switch (handler)
 678         {
 679         case iconveh_error:
 680           ASSERT (result == NULL && errno == EILSEQ);
 681           break;
 682         case iconveh_question_mark:
 683         case iconveh_escape_sequence:
 684           {
 685             static const char expected[] = "Rafa? Maszkowski";
 686             ASSERT (result != NULL);
 687             ASSERT (strcmp (result, expected) == 0);
 688             free (result);
 689           }
 690           break;
 691         }
 692     }
 693 
 694   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
 695   for (h = 0; h < SIZEOF (handlers); h++)
 696     {
 697       enum iconv_ilseq_handler handler = handlers[h];
 698       static const char input[] = "Costs: 27 \342\202\254"; /* EURO SIGN */
 699       char *result = str_cd_iconveh (input,
 700                                      &cdeh_utf8_to_88591,
 701                                      handler);
 702       switch (handler)
 703         {
 704         case iconveh_error:
 705           ASSERT (result == NULL && errno == EILSEQ);
 706           break;
 707         case iconveh_question_mark:
 708           {
 709             static const char expected[] = "Costs: 27 ?";
 710             ASSERT (result != NULL);
 711             ASSERT (strcmp (result, expected) == 0);
 712             free (result);
 713           }
 714           break;
 715         case iconveh_escape_sequence:
 716           {
 717             static const char expected[] = "Costs: 27 \\u20AC";
 718             ASSERT (result != NULL);
 719             ASSERT (strcmp (result, expected) == 0);
 720             free (result);
 721           }
 722           break;
 723         }
 724     }
 725 
 726   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
 727   for (h = 0; h < SIZEOF (handlers); h++)
 728     {
 729       enum iconv_ilseq_handler handler = handlers[h];
 730       static const char input[] = "\342";
 731       char *result = str_cd_iconveh (input,
 732                                      &cdeh_utf8_to_88591,
 733                                      handler);
 734       ASSERT (result != NULL);
 735       ASSERT (strcmp (result, "") == 0);
 736       free (result);
 737     }
 738 
 739   if (cd_88591_to_88592 != (iconv_t)(-1))
 740     iconv_close (cd_88591_to_88592);
 741   if (cd_88592_to_88591 != (iconv_t)(-1))
 742     iconv_close (cd_88592_to_88591);
 743   iconv_close (cd_88591_to_utf8);
 744   iconv_close (cd_utf8_to_88591);
 745   iconv_close (cd_88592_to_utf8);
 746   iconv_close (cd_utf8_to_88592);
 747 
 748   /* ------------------------- Test mem_iconveh() ------------------------- */
 749 
 750   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
 751   for (h = 0; h < SIZEOF (handlers); h++)
 752     {
 753       enum iconv_ilseq_handler handler = handlers[h];
 754       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 755       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 756       for (o = 0; o < 2; o++)
 757         {
 758           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 759           char *result = NULL;
 760           size_t length = 0;
 761           int retval = mem_iconveh (input, strlen (input),
 762                                     "ISO-8859-2", "ISO-8859-1",
 763                                     handler,
 764                                     offsets,
 765                                     &result, &length);
 766           ASSERT (retval == 0);
 767           ASSERT (length == strlen (expected));
 768           ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 769           if (o)
 770             {
 771               for (i = 0; i < 37; i++)
 772                 ASSERT (offsets[i] == i);
 773               ASSERT (offsets[37] == MAGIC);
 774               free (offsets);
 775             }
 776           free (result);
 777         }
 778     }
 779 
 780   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
 781   for (h = 0; h < SIZEOF (handlers); h++)
 782     {
 783       enum iconv_ilseq_handler handler = handlers[h];
 784       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
 785       for (o = 0; o < 2; o++)
 786         {
 787           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 788           char *result = NULL;
 789           size_t length = 0;
 790           int retval = mem_iconveh (input, strlen (input),
 791                                     "ISO-8859-2", "ISO-8859-1",
 792                                     handler,
 793                                     offsets,
 794                                     &result, &length);
 795           switch (handler)
 796             {
 797             case iconveh_error:
 798               ASSERT (retval == -1 && errno == EILSEQ);
 799               ASSERT (result == NULL);
 800               if (o)
 801                 free (offsets);
 802               break;
 803             case iconveh_question_mark:
 804               {
 805                 static const char expected[] = "Rafa? Maszkowski";
 806                 ASSERT (retval == 0);
 807                 ASSERT (length == strlen (expected));
 808                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 809                 if (o)
 810                   {
 811                     for (i = 0; i < 16; i++)
 812                       ASSERT (offsets[i] == i);
 813                     ASSERT (offsets[16] == MAGIC);
 814                     free (offsets);
 815                   }
 816                 free (result);
 817               }
 818               break;
 819             case iconveh_escape_sequence:
 820               {
 821                 static const char expected[] = "Rafa\\u0142 Maszkowski";
 822                 ASSERT (retval == 0);
 823                 ASSERT (length == strlen (expected));
 824                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 825                 if (o)
 826                   {
 827                     for (i = 0; i < 16; i++)
 828                       ASSERT (offsets[i] == (i < 5 ? i :
 829                                              i + 5));
 830                     ASSERT (offsets[16] == MAGIC);
 831                     free (offsets);
 832                   }
 833                 free (result);
 834               }
 835               break;
 836             }
 837         }
 838     }
 839 
 840   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
 841   for (h = 0; h < SIZEOF (handlers); h++)
 842     {
 843       enum iconv_ilseq_handler handler = handlers[h];
 844       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 845       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
 846       for (o = 0; o < 2; o++)
 847         {
 848           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 849           char *result = NULL;
 850           size_t length = 0;
 851           int retval = mem_iconveh (input, strlen (input),
 852                                     "ISO-8859-1", "UTF-8",
 853                                     handler,
 854                                     offsets,
 855                                     &result, &length);
 856           ASSERT (retval == 0);
 857           ASSERT (length == strlen (expected));
 858           ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 859           if (o)
 860             {
 861               for (i = 0; i < 37; i++)
 862                 ASSERT (offsets[i] == (i < 1 ? i :
 863                                        i < 12 ? i + 1 :
 864                                        i < 18 ? i + 2 :
 865                                        i + 3));
 866               ASSERT (offsets[37] == MAGIC);
 867               free (offsets);
 868             }
 869           free (result);
 870         }
 871     }
 872 
 873   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
 874   for (h = 0; h < SIZEOF (handlers); h++)
 875     {
 876       enum iconv_ilseq_handler handler = handlers[h];
 877       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
 878       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
 879       for (o = 0; o < 2; o++)
 880         {
 881           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 882           char *result = NULL;
 883           size_t length = 0;
 884           int retval = mem_iconveh (input, strlen (input),
 885                                     "UTF-8", "ISO-8859-1",
 886                                     handler,
 887                                     offsets,
 888                                     &result, &length);
 889           ASSERT (retval == 0);
 890           ASSERT (length == strlen (expected));
 891           ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 892           if (o)
 893             {
 894               for (i = 0; i < 41; i++)
 895                 ASSERT (offsets[i] == (i < 1 ? i :
 896                                        i == 1 ? (size_t)(-1) :
 897                                        i < 13 ? i - 1 :
 898                                        i == 13 ? (size_t)(-1) :
 899                                        i < 20 ? i - 2 :
 900                                        i == 20 ? (size_t)(-1) :
 901                                        i < 40 ? i - 3 :
 902                                        (size_t)(-1)));
 903               ASSERT (offsets[41] == MAGIC);
 904               free (offsets);
 905             }
 906           free (result);
 907         }
 908     }
 909 
 910   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
 911   for (h = 0; h < SIZEOF (handlers); h++)
 912     {
 913       enum iconv_ilseq_handler handler = handlers[h];
 914       static const char input[] = "Rafa\305\202 Maszkowski"; /* Rafał Maszkowski */
 915       for (o = 0; o < 2; o++)
 916         {
 917           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 918           char *result = NULL;
 919           size_t length = 0;
 920           int retval = mem_iconveh (input, strlen (input),
 921                                     "UTF-8", "ISO-8859-1",
 922                                     handler,
 923                                     offsets,
 924                                     &result, &length);
 925           switch (handler)
 926             {
 927             case iconveh_error:
 928               ASSERT (retval == -1 && errno == EILSEQ);
 929               ASSERT (result == NULL);
 930               if (o)
 931                 free (offsets);
 932               break;
 933             case iconveh_question_mark:
 934               {
 935                 static const char expected[] = "Rafa? Maszkowski";
 936                 ASSERT (retval == 0);
 937                 ASSERT (length == strlen (expected));
 938                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 939                 if (o)
 940                   {
 941                     for (i = 0; i < 17; i++)
 942                       ASSERT (offsets[i] == (i < 5 ? i :
 943                                              i == 5 ? (size_t)(-1) :
 944                                              i - 1));
 945                     ASSERT (offsets[17] == MAGIC);
 946                     free (offsets);
 947                   }
 948                 free (result);
 949               }
 950               break;
 951             case iconveh_escape_sequence:
 952               {
 953                 static const char expected[] = "Rafa\\u0142 Maszkowski";
 954                 ASSERT (retval == 0);
 955                 ASSERT (length == strlen (expected));
 956                 ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
 957                 if (o)
 958                   {
 959                     for (i = 0; i < 17; i++)
 960                       ASSERT (offsets[i] == (i < 5 ? i :
 961                                              i == 5 ? (size_t)(-1) :
 962                                              i + 4));
 963                     ASSERT (offsets[17] == MAGIC);
 964                     free (offsets);
 965                   }
 966                 free (result);
 967               }
 968               break;
 969             }
 970         }
 971     }
 972 
 973   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
 974   for (h = 0; h < SIZEOF (handlers); h++)
 975     {
 976       enum iconv_ilseq_handler handler = handlers[h];
 977       static const char input[] = "\342";
 978       for (o = 0; o < 2; o++)
 979         {
 980           size_t *offsets = (o ? new_offsets (strlen (input)) : NULL);
 981           char *result = NULL;
 982           size_t length = 0;
 983           int retval = mem_iconveh (input, strlen (input),
 984                                     "UTF-8", "ISO-8859-1",
 985                                     handler,
 986                                     offsets,
 987                                     &result, &length);
 988           ASSERT (retval == 0);
 989           ASSERT (length == 0);
 990           if (o)
 991             {
 992               ASSERT (offsets[0] == 0);
 993               ASSERT (offsets[1] == MAGIC);
 994               free (offsets);
 995             }
 996           free (result);
 997         }
 998     }
 999 
1000   /* ------------------------- Test str_iconveh() ------------------------- */
1001 
1002   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
1003   for (h = 0; h < SIZEOF (handlers); h++)
1004     {
1005       enum iconv_ilseq_handler handler = handlers[h];
1006       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
1007       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
1008       char *result = str_iconveh (input, "ISO-8859-2", "ISO-8859-1", handler);
1009       ASSERT (result != NULL);
1010       ASSERT (strcmp (result, expected) == 0);
1011       free (result);
1012     }
1013 
1014   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
1015   for (h = 0; h < SIZEOF (handlers); h++)
1016     {
1017       enum iconv_ilseq_handler handler = handlers[h];
1018       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
1019       char *result = str_iconveh (input, "ISO-8859-2", "ISO-8859-1", handler);
1020       switch (handler)
1021         {
1022         case iconveh_error:
1023           ASSERT (result == NULL && errno == EILSEQ);
1024           break;
1025         case iconveh_question_mark:
1026           {
1027             static const char expected[] = "Rafa? Maszkowski";
1028             ASSERT (result != NULL);
1029             ASSERT (strcmp (result, expected) == 0);
1030             free (result);
1031           }
1032           break;
1033         case iconveh_escape_sequence:
1034           {
1035             static const char expected[] = "Rafa\\u0142 Maszkowski";
1036             ASSERT (result != NULL);
1037             ASSERT (strcmp (result, expected) == 0);
1038             free (result);
1039           }
1040           break;
1041         }
1042     }
1043 
1044   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
1045   for (h = 0; h < SIZEOF (handlers); h++)
1046     {
1047       enum iconv_ilseq_handler handler = handlers[h];
1048       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
1049       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
1050       char *result = str_iconveh (input, "ISO-8859-1", "UTF-8", handler);
1051       ASSERT (result != NULL);
1052       ASSERT (strcmp (result, expected) == 0);
1053       free (result);
1054     }
1055 
1056   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
1057   for (h = 0; h < SIZEOF (handlers); h++)
1058     {
1059       enum iconv_ilseq_handler handler = handlers[h];
1060       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
1061       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
1062       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
1063       ASSERT (result != NULL);
1064       ASSERT (strcmp (result, expected) == 0);
1065       free (result);
1066     }
1067 
1068   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
1069   for (h = 0; h < SIZEOF (handlers); h++)
1070     {
1071       enum iconv_ilseq_handler handler = handlers[h];
1072       static const char input[] = "Costs: 27 \342\202\254"; /* EURO SIGN */
1073       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
1074       switch (handler)
1075         {
1076         case iconveh_error:
1077           ASSERT (result == NULL && errno == EILSEQ);
1078           break;
1079         case iconveh_question_mark:
1080           {
1081             static const char expected[] = "Costs: 27 ?";
1082             ASSERT (result != NULL);
1083             ASSERT (strcmp (result, expected) == 0);
1084             free (result);
1085           }
1086           break;
1087         case iconveh_escape_sequence:
1088           {
1089             static const char expected[] = "Costs: 27 \\u20AC";
1090             ASSERT (result != NULL);
1091             ASSERT (strcmp (result, expected) == 0);
1092             free (result);
1093           }
1094           break;
1095         }
1096     }
1097 
1098   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
1099   for (h = 0; h < SIZEOF (handlers); h++)
1100     {
1101       enum iconv_ilseq_handler handler = handlers[h];
1102       static const char input[] = "\342";
1103       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
1104       ASSERT (result != NULL);
1105       ASSERT (strcmp (result, "") == 0);
1106       free (result);
1107     }
1108 
1109   /* -------------------------------- Done. -------------------------------- */
1110 
1111   if (cd_ascii_to_88591 != (iconv_t)(-1))
1112     iconv_close (cd_ascii_to_88591);
1113   iconv_close (cd_ascii_to_utf8);
1114   if (cd_utf7_to_utf8 != (iconv_t)(-1))
1115     iconv_close (cd_utf7_to_utf8);
1116 
1117 #endif
1118 
1119   return 0;
1120 }

/* [previous][next][first][last][top][bottom][index][help] */