~ubuntu-branches/ubuntu/natty/diffutils/natty

« back to all changes in this revision

Viewing changes to lib/mbsrtowcs.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2010-05-04 20:38:00 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100504203800-f67xd9rsa9xl9qqj
Tags: 1:3.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Convert string to wide string.
 
2
   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 
3
   Written by Bruno Haible <bruno@clisp.org>, 2008.
 
4
 
 
5
   This program is free software: you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; either version 3 of the License, or
 
8
   (at your option) any later version.
 
9
 
 
10
   This program is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
   GNU General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License
 
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
17
 
 
18
#include <config.h>
 
19
 
 
20
/* Specification.  */
 
21
#include <wchar.h>
 
22
 
 
23
#include <errno.h>
 
24
#include <limits.h>
 
25
#include <stdlib.h>
 
26
 
 
27
#include "strnlen1.h"
 
28
 
 
29
 
 
30
extern mbstate_t _gl_mbsrtowcs_state;
 
31
 
 
32
size_t
 
33
mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps)
 
34
{
 
35
  if (ps == NULL)
 
36
    ps = &_gl_mbsrtowcs_state;
 
37
  {
 
38
    const char *src = *srcp;
 
39
 
 
40
    if (dest != NULL)
 
41
      {
 
42
        wchar_t *destptr = dest;
 
43
 
 
44
        for (; len > 0; destptr++, len--)
 
45
          {
 
46
            size_t src_avail;
 
47
            size_t ret;
 
48
 
 
49
            /* An optimized variant of
 
50
               src_avail = strnlen1 (src, MB_LEN_MAX);  */
 
51
            if (src[0] == '\0')
 
52
              src_avail = 1;
 
53
            else if (src[1] == '\0')
 
54
              src_avail = 2;
 
55
            else if (src[2] == '\0')
 
56
              src_avail = 3;
 
57
            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
 
58
              src_avail = 4;
 
59
            else
 
60
              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
 
61
 
 
62
            /* Parse the next multibyte character.  */
 
63
            ret = mbrtowc (destptr, src, src_avail, ps);
 
64
 
 
65
            if (ret == (size_t)(-2))
 
66
              /* Encountered a multibyte character that extends past a '\0' byte
 
67
                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
 
68
              abort ();
 
69
 
 
70
            if (ret == (size_t)(-1))
 
71
              goto bad_input;
 
72
            if (ret == 0)
 
73
              {
 
74
                src = NULL;
 
75
                /* Here mbsinit (ps).  */
 
76
                break;
 
77
              }
 
78
            src += ret;
 
79
          }
 
80
 
 
81
        *srcp = src;
 
82
        return destptr - dest;
 
83
      }
 
84
    else
 
85
      {
 
86
        /* Ignore dest and len, don't store *srcp at the end, and
 
87
           don't clobber *ps.  */
 
88
        mbstate_t state = *ps;
 
89
        size_t totalcount = 0;
 
90
 
 
91
        for (;; totalcount++)
 
92
          {
 
93
            size_t src_avail;
 
94
            size_t ret;
 
95
 
 
96
            /* An optimized variant of
 
97
               src_avail = strnlen1 (src, MB_LEN_MAX);  */
 
98
            if (src[0] == '\0')
 
99
              src_avail = 1;
 
100
            else if (src[1] == '\0')
 
101
              src_avail = 2;
 
102
            else if (src[2] == '\0')
 
103
              src_avail = 3;
 
104
            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
 
105
              src_avail = 4;
 
106
            else
 
107
              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
 
108
 
 
109
            /* Parse the next multibyte character.  */
 
110
            ret = mbrtowc (NULL, src, src_avail, &state);
 
111
 
 
112
            if (ret == (size_t)(-2))
 
113
              /* Encountered a multibyte character that extends past a '\0' byte
 
114
                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
 
115
              abort ();
 
116
 
 
117
            if (ret == (size_t)(-1))
 
118
              goto bad_input2;
 
119
            if (ret == 0)
 
120
              {
 
121
                /* Here mbsinit (&state).  */
 
122
                break;
 
123
              }
 
124
            src += ret;
 
125
          }
 
126
 
 
127
        return totalcount;
 
128
      }
 
129
 
 
130
   bad_input:
 
131
    *srcp = src;
 
132
   bad_input2:
 
133
    errno = EILSEQ;
 
134
    return (size_t)(-1);
 
135
  }
 
136
}