Coverage Report

Created: 2025-08-29 06:28

/src/fribidi/lib/fribidi.c
Line
Count
Source (jump to first uncovered line)
1
/* FriBidi
2
 * fribidi.c - Unicode bidirectional and Arabic joining/shaping algorithms
3
 *
4
 * Authors:
5
 *   Behdad Esfahbod, 2001, 2002, 2004
6
 *   Dov Grobgeld, 1999, 2000
7
 *
8
 * Copyright (C) 2004 Sharif FarsiWeb, Inc
9
 * Copyright (C) 2001,2002 Behdad Esfahbod
10
 * Copyright (C) 1999,2000 Dov Grobgeld
11
 * 
12
 * This library is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU Lesser General Public
14
 * License as published by the Free Software Foundation; either
15
 * version 2.1 of the License, or (at your option) any later version.
16
 * 
17
 * This library is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20
 * Lesser General Public License for more details.
21
 * 
22
 * You should have received a copy of the GNU Lesser General Public License
23
 * along with this library, in a file named COPYING; if not, write to the
24
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25
 * Boston, MA 02110-1301, USA
26
 * 
27
 * For licensing issues, contact <fribidi.license@gmail.com>.
28
 */
29
30
#include "common.h"
31
32
#include <fribidi.h>
33
34
#ifdef DEBUG
35
static int flag_debug = false;
36
#endif
37
38
FRIBIDI_ENTRY fribidi_boolean
39
fribidi_debug_status (
40
  void
41
)
42
40.1k
{
43
40.1k
#ifdef DEBUG
44
40.1k
  return flag_debug;
45
#else
46
  return false;
47
#endif
48
40.1k
}
49
50
FRIBIDI_ENTRY fribidi_boolean
51
fribidi_set_debug (
52
  /* input */
53
  fribidi_boolean state
54
)
55
0
{
56
0
#ifdef DEBUG
57
0
  return flag_debug = state;
58
#else
59
  return false;
60
#endif
61
0
}
62
63
FRIBIDI_ENTRY FriBidiStrIndex
64
fribidi_remove_bidi_marks (
65
  FriBidiChar *str,
66
  const FriBidiStrIndex len,
67
  FriBidiStrIndex *positions_to_this,
68
  FriBidiStrIndex *position_from_this_list,
69
  FriBidiLevel *embedding_levels
70
)
71
0
{
72
0
  register FriBidiStrIndex i, j = 0;
73
0
  fribidi_boolean private_from_this = false;
74
0
  fribidi_boolean status = false;
75
76
0
  if UNLIKELY
77
0
    (len == 0 || str == NULL)
78
0
    {
79
0
      status = true;
80
0
      goto out;
81
0
    }
82
83
0
  DBG ("in fribidi_remove_bidi_marks");
84
85
0
  fribidi_assert (str);
86
87
  /* If to_this is not NULL, we must have from_this as well. If it is
88
     not given by the caller, we have to make a private instance of it. */
89
0
  if (positions_to_this && !position_from_this_list)
90
0
    {
91
0
      position_from_this_list = fribidi_malloc (sizeof
92
0
            (position_from_this_list[0]) *
93
0
            len);
94
0
      if UNLIKELY
95
0
  (!position_from_this_list) goto out;
96
0
      private_from_this = true;
97
0
      for (i = 0; i < len; i++)
98
0
  position_from_this_list[positions_to_this[i]] = i;
99
0
    }
100
101
0
  for (i = 0; i < len; i++)
102
0
    if (!FRIBIDI_IS_EXPLICIT_OR_BN (fribidi_get_bidi_type (str[i]))
103
0
        && !FRIBIDI_IS_ISOLATE (fribidi_get_bidi_type (str[i]))
104
0
  && str[i] != FRIBIDI_CHAR_LRM && str[i] != FRIBIDI_CHAR_RLM)
105
0
      {
106
0
  str[j] = str[i];
107
0
  if (embedding_levels)
108
0
    embedding_levels[j] = embedding_levels[i];
109
0
  if (position_from_this_list)
110
0
    position_from_this_list[j] = position_from_this_list[i];
111
0
  j++;
112
0
      }
113
114
  /* Convert the from_this list to to_this */
115
0
  if (positions_to_this)
116
0
    {
117
0
      for (i = 0; i < len; i++)
118
0
  positions_to_this[i] = -1;
119
0
      for (i = 0; i < len; i++)
120
0
  positions_to_this[position_from_this_list[i]] = i;
121
0
    }
122
123
0
  status = true;
124
125
0
out:
126
127
0
  if (private_from_this)
128
0
    fribidi_free (position_from_this_list);
129
130
0
  return status ? j : -1;
131
0
}
132
133
/* Local array size, used for stack-based local arrays */
134
0
#define LOCAL_LIST_SIZE 128
135
static FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
136
137
138
FRIBIDI_ENTRY FriBidiLevel
139
fribidi_log2vis (
140
  /* input */
141
  const FriBidiChar *str,
142
  const FriBidiStrIndex len,
143
  /* input and output */
144
  FriBidiParType *pbase_dir,
145
  /* output */
146
  FriBidiChar *visual_str,
147
  FriBidiStrIndex *positions_L_to_V,
148
  FriBidiStrIndex *positions_V_to_L,
149
  FriBidiLevel *embedding_levels
150
)
151
0
{
152
0
  register FriBidiStrIndex i;
153
0
  FriBidiLevel max_level = 0;
154
0
  fribidi_boolean private_V_to_L = false;
155
0
  fribidi_boolean private_embedding_levels = false;
156
0
  fribidi_boolean status = false;
157
0
  FriBidiArabicProp local_ar_props[LOCAL_LIST_SIZE];
158
0
  FriBidiArabicProp *ar_props = NULL;
159
0
  FriBidiLevel local_embedding_levels[LOCAL_LIST_SIZE];
160
0
  FriBidiCharType local_bidi_types[LOCAL_LIST_SIZE];
161
0
  FriBidiCharType *bidi_types = NULL;
162
0
  FriBidiBracketType local_bracket_types[LOCAL_LIST_SIZE];
163
0
  FriBidiBracketType *bracket_types = NULL;
164
0
  FriBidiStrIndex local_positions_V_to_L[LOCAL_LIST_SIZE];
165
166
0
  if UNLIKELY
167
0
    (len == 0)
168
0
    {
169
0
      status = true;
170
0
      goto out;
171
0
    }
172
173
0
  DBG ("in fribidi_log2vis");
174
175
0
  fribidi_assert (str);
176
0
  fribidi_assert (pbase_dir);
177
178
0
  if (len < LOCAL_LIST_SIZE)
179
0
    bidi_types = local_bidi_types;
180
0
  else
181
0
    bidi_types = fribidi_malloc (len * sizeof bidi_types[0]);
182
0
  if (!bidi_types)
183
0
    goto out;
184
185
0
  fribidi_get_bidi_types (str, len, bidi_types);
186
187
0
  if (len < LOCAL_LIST_SIZE)
188
0
    bracket_types = local_bracket_types;
189
0
  else
190
0
    bracket_types = fribidi_malloc (len * sizeof bracket_types[0]);
191
    
192
0
  if (!bracket_types)
193
0
    goto out;
194
195
0
  fribidi_get_bracket_types (str, len, bidi_types,
196
                             /* output */
197
0
                             bracket_types);
198
0
  if (!embedding_levels)
199
0
    {
200
0
      if (len < LOCAL_LIST_SIZE)
201
0
        embedding_levels = local_embedding_levels;
202
0
      else
203
0
        embedding_levels = fribidi_malloc (len * sizeof embedding_levels[0]);
204
0
      if (!embedding_levels)
205
0
  goto out;
206
0
      private_embedding_levels = true;
207
0
    }
208
209
0
  max_level = fribidi_get_par_embedding_levels_ex (bidi_types,
210
0
                                                   bracket_types,
211
0
                                                   len,
212
0
                                                   pbase_dir,
213
0
                                                   embedding_levels) - 1;
214
0
  if UNLIKELY
215
0
    (max_level < 0) goto out;
216
217
  /* If l2v is to be calculated we must have v2l as well. If it is not
218
     given by the caller, we have to make a private instance of it. */
219
0
  if (positions_L_to_V && !positions_V_to_L)
220
0
    {
221
0
      if (len < LOCAL_LIST_SIZE)
222
0
        positions_V_to_L = local_positions_V_to_L;
223
0
      else
224
0
        positions_V_to_L =
225
0
  (FriBidiStrIndex *) fribidi_malloc (sizeof (FriBidiStrIndex) * len);
226
0
      if (!positions_V_to_L)
227
0
  goto out;
228
0
      private_V_to_L = true;
229
0
    }
230
231
  /* Set up the ordering array to identity order */
232
0
  if (positions_V_to_L)
233
0
    {
234
0
      for (i = 0; i < len; i++)
235
0
  positions_V_to_L[i] = i;
236
0
    }
237
238
239
0
  if (visual_str)
240
0
    {
241
      /* Using memcpy instead
242
      for (i = len - 1; i >= 0; i--)
243
  visual_str[i] = str[i];
244
      */
245
0
      memcpy (visual_str, str, len * sizeof (*visual_str));
246
247
      /* Arabic joining */
248
0
      if (len < LOCAL_LIST_SIZE)
249
0
        ar_props = local_ar_props;
250
0
      else
251
0
        ar_props = fribidi_malloc (len * sizeof ar_props[0]);
252
0
      fribidi_get_joining_types (str, len, ar_props);
253
0
      fribidi_join_arabic (bidi_types, len, embedding_levels, ar_props);
254
255
0
      fribidi_shape (flags, embedding_levels, len, ar_props, visual_str);
256
0
    }
257
258
  /* line breaking goes here, but we assume one line in this function */
259
260
  /* and this should be called once per line, but again, we assume one
261
   * line in this deprecated function */
262
0
  status =
263
0
    fribidi_reorder_line (flags, bidi_types, len, 0, *pbase_dir,
264
0
        embedding_levels, visual_str,
265
0
        positions_V_to_L);
266
267
  /* Convert the v2l list to l2v */
268
0
  if (positions_L_to_V)
269
0
    {
270
0
      for (i = 0; i < len; i++)
271
0
  positions_L_to_V[i] = -1;
272
0
      for (i = 0; i < len; i++)
273
0
  positions_L_to_V[positions_V_to_L[i]] = i;
274
0
    }
275
276
0
out:
277
278
0
  if (private_V_to_L && positions_V_to_L != local_positions_V_to_L)
279
0
    fribidi_free (positions_V_to_L);
280
281
0
  if (private_embedding_levels && embedding_levels != local_embedding_levels)
282
0
    fribidi_free (embedding_levels);
283
284
0
  if (ar_props && ar_props != local_ar_props)
285
0
    fribidi_free (ar_props);
286
287
0
  if (bidi_types && bidi_types != local_bidi_types)
288
0
    fribidi_free (bidi_types);
289
290
0
  if (bracket_types && bracket_types != local_bracket_types)
291
0
    fribidi_free (bracket_types);
292
293
0
  return status ? max_level + 1 : 0;
294
0
}
295
296
const char *fribidi_unicode_version = FRIBIDI_UNICODE_VERSION;
297
298
const char *fribidi_version_info =
299
  "(" FRIBIDI_NAME ") " FRIBIDI_VERSION "\n"
300
  "interface version " FRIBIDI_INTERFACE_VERSION_STRING ",\n"
301
  "Unicode Character Database version " FRIBIDI_UNICODE_VERSION ",\n"
302
  "Configure options"
303
#ifdef DEBUG
304
  " --enable-debug"
305
#endif /* DEBUG */
306
  ".\n\n"
307
  "Copyright (C) 2004  Sharif FarsiWeb, Inc.\n"
308
  "Copyright (C) 2001, 2002, 2004, 2005  Behdad Esfahbod\n"
309
  "Copyright (C) 1999, 2000, 2017, 2018, 2019  Dov Grobgeld\n"
310
  FRIBIDI_NAME " comes with NO WARRANTY, to the extent permitted by law.\n"
311
  "You may redistribute copies of " FRIBIDI_NAME " under\n"
312
  "the terms of the GNU Lesser General Public License.\n"
313
  "For more information about these matters, see the file named COPYING.\n\n"
314
  "Written by Behdad Esfahbod and Dov Grobgeld.\n";
315
316
/* Editor directions:
317
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
318
 */