~ubuntu-branches/ubuntu/maverick/swig1.3/maverick

« back to all changes in this revision

Viewing changes to Lib/perl5/ptrlang.i

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Landschoff
  • Date: 2002-03-29 01:56:07 UTC
  • Revision ID: james.westby@ubuntu.com-20020329015607-c0wt03xu8oy9ioj7
Tags: upstream-1.3.11
ImportĀ upstreamĀ versionĀ 1.3.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// SWIG pointer conversion and utility library
 
3
// 
 
4
// Dave Beazley
 
5
// April 19, 1997
 
6
//
 
7
// Perl5 specific implementation.   This file is included
 
8
// by the file ../pointer.i
 
9
 
 
10
%{
 
11
#include <ctype.h>
 
12
 
 
13
/* Types used by the library */
 
14
static swig_type_info *SWIG_POINTER_int_p = 0;
 
15
static swig_type_info *SWIG_POINTER_short_p =0;
 
16
static swig_type_info *SWIG_POINTER_long_p = 0;
 
17
static swig_type_info *SWIG_POINTER_float_p = 0;
 
18
static swig_type_info *SWIG_POINTER_double_p = 0;
 
19
static swig_type_info *SWIG_POINTER_char_p = 0;
 
20
static swig_type_info *SWIG_POINTER_char_pp = 0;
 
21
static swig_type_info *SWIG_POINTER_void_p = 0;
 
22
%}
 
23
 
 
24
%init %{
 
25
  SWIG_POINTER_int_p = SWIG_TypeQuery("int *");
 
26
  SWIG_POINTER_short_p = SWIG_TypeQuery("short *");
 
27
  SWIG_POINTER_long_p = SWIG_TypeQuery("long *");
 
28
  SWIG_POINTER_float_p = SWIG_TypeQuery("float *");
 
29
  SWIG_POINTER_double_p = SWIG_TypeQuery("double *");
 
30
  SWIG_POINTER_char_p = SWIG_TypeQuery("char *");
 
31
  SWIG_POINTER_char_pp = SWIG_TypeQuery("char **");
 
32
  SWIG_POINTER_void_p = SWIG_TypeQuery("void *");
 
33
%}
 
34
 
 
35
%{
 
36
 
 
37
/* #ifdef WIN32
 
38
#undef isspace
 
39
#define isspace(c) (c == ' ')
 
40
#endif
 
41
*/
 
42
 
 
43
/*------------------------------------------------------------------
 
44
  ptrvalue(ptr,type = 0)
 
45
 
 
46
  Attempts to dereference a pointer value.  If type is given, it 
 
47
  will try to use that type.  Otherwise, this function will attempt
 
48
  to "guess" the proper datatype by checking against all of the 
 
49
  builtin C datatypes. 
 
50
  ------------------------------------------------------------------ */
 
51
 
 
52
#ifdef PERL_OBJECT
 
53
static SV *_ptrvalue(CPerlObj *pPerl,SV *_PTRVALUE, int index, const char *type) {
 
54
#define ptrvalue(a,b,c) _ptrvalue(pPerl,a,b,c)
 
55
#else
 
56
static SV *_ptrvalue(SV *_PTRVALUE, int index, const char *type) {
 
57
#define ptrvalue(a,b,c) _ptrvalue(a,b,c)
 
58
#endif
 
59
 
 
60
  void     *ptr;
 
61
  SV       *obj = 0;
 
62
 
 
63
  if (SWIG_ConvertPtr(_PTRVALUE, &ptr, 0) < 0) {
 
64
    croak("Type error it ptrvalue. Argument is not a valid pointer value.");
 
65
  } else {
 
66
    /* If no datatype was passed, try a few common datatypes first */
 
67
    if (!type) {
 
68
 
 
69
      /* No datatype was passed.   Type to figure out if it's a common one */
 
70
      
 
71
      if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_int_p) >= 0) {
 
72
        type = "int";
 
73
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_double_p) >= 0) {
 
74
        type = "double";
 
75
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_short_p) >= 0) {
 
76
        type = "short";
 
77
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_long_p) >= 0) {
 
78
        type = "long";
 
79
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_float_p) >= 0) {
 
80
        type = "float";
 
81
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_char_p) >= 0) {
 
82
        type = "char";
 
83
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_char_pp) >= 0) {
 
84
        type = "char *";
 
85
      } else {
 
86
        type = "unknown";
 
87
      }
 
88
    }
 
89
    
 
90
    if (!ptr) {
 
91
      croak("Unable to dereference NULL pointer.");
 
92
      return 0;
 
93
    }
 
94
 
 
95
    /* Now we have a datatype.  Try to figure out what to do about it */
 
96
    if (strcmp(type,"int") == 0) {
 
97
      obj = sv_newmortal();
 
98
      sv_setiv(obj,(IV) *(((int *) ptr) + index));
 
99
    } else if (strcmp(type,"double") == 0) {
 
100
      obj = sv_newmortal();
 
101
      sv_setnv(obj,(double) *(((double *) ptr)+index));
 
102
    } else if (strcmp(type,"short") == 0) {
 
103
      obj = sv_newmortal();
 
104
      sv_setiv(obj,(IV) *(((short *) ptr) + index));
 
105
    } else if (strcmp(type,"long") == 0) {
 
106
      obj = sv_newmortal();
 
107
      sv_setiv(obj,(IV) *(((long *) ptr) + index));
 
108
    } else if (strcmp(type,"float") == 0) {
 
109
      obj = sv_newmortal();
 
110
      sv_setnv(obj,(double) *(((float *) ptr)+index));
 
111
    } else if (strcmp(type,"char") == 0) {
 
112
      obj = sv_newmortal();
 
113
      sv_setpv(obj,((char *) ptr)+index);
 
114
    } else if (strcmp(type,"char *") == 0) {
 
115
      char *c = *(((char **) ptr)+index);
 
116
      obj = sv_newmortal();
 
117
      if (c) 
 
118
        sv_setpv(obj,c);
 
119
      else 
 
120
        sv_setpv(obj,"NULL");
 
121
    } else {
 
122
      croak("Unable to dereference unsupported datatype.");
 
123
      obj = 0;
 
124
    }
 
125
  }
 
126
  return obj;
 
127
}
 
128
 
 
129
/*------------------------------------------------------------------
 
130
  ptrcreate(type,value = 0,numelements = 1)
 
131
 
 
132
  Attempts to create a new object of given type.  Type must be
 
133
  a basic C datatype.  Will not create complex objects.
 
134
  ------------------------------------------------------------------ */
 
135
#ifdef PERL_OBJECT
 
136
static SV *_ptrcreate(CPerlObj *pPerl, char *type, SV *value, int numelements) {
 
137
#define ptrcreate(a,b,c) _ptrcreate(pPerl,a,b,c)
 
138
#else
 
139
static SV *_ptrcreate(char *type, SV *value, int numelements) {
 
140
#define ptrcreate(a,b,c) _ptrcreate(a,b,c)
 
141
#endif
 
142
 
 
143
  void     *ptr;
 
144
  SV       *obj;
 
145
  int       sz;
 
146
  swig_type_info *cast = 0;
 
147
 
 
148
  /* Check the type string against a variety of possibilities */
 
149
 
 
150
  if (strcmp(type,"int") == 0) {
 
151
    sz = sizeof(int)*numelements;
 
152
    cast = SWIG_POINTER_int_p;
 
153
  } else if (strcmp(type,"short") == 0) {
 
154
    sz = sizeof(short)*numelements;
 
155
    cast = SWIG_POINTER_short_p;
 
156
  } else if (strcmp(type,"long") == 0) {
 
157
    sz = sizeof(long)*numelements;
 
158
    cast = SWIG_POINTER_long_p;
 
159
  } else if (strcmp(type,"double") == 0) {
 
160
    sz = sizeof(double)*numelements;
 
161
    cast = SWIG_POINTER_double_p;
 
162
  } else if (strcmp(type,"float") == 0) {
 
163
    sz = sizeof(float)*numelements;
 
164
    cast = SWIG_POINTER_float_p;
 
165
  } else if (strcmp(type,"char") == 0) {
 
166
    sz = sizeof(char)*numelements;
 
167
    cast = SWIG_POINTER_char_p;
 
168
  } else if (strcmp(type,"char *") == 0) {
 
169
    sz = sizeof(char *)*(numelements+1);
 
170
    cast = SWIG_POINTER_char_pp;
 
171
  } else if (strcmp(type,"void") == 0) {
 
172
    sz = numelements;
 
173
    cast = SWIG_POINTER_void_p; 
 
174
  } else {
 
175
    croak("Unable to create unknown datatype."); 
 
176
    return 0;
 
177
  }
 
178
   
 
179
  /* Create the new object */
 
180
  
 
181
  ptr = (void *) calloc(1,sz);
 
182
  if (!ptr) {
 
183
    croak("Out of memory in ptrcreate."); 
 
184
    return 0;
 
185
  }
 
186
 
 
187
  /* Now try to set its default value */
 
188
 
 
189
  if (value) {
 
190
    if (strcmp(type,"int") == 0) {
 
191
      int *ip,i,ivalue;
 
192
      ivalue = (int) SvIV(value);
 
193
      ip = (int *) ptr;
 
194
      for (i = 0; i < numelements; i++)
 
195
        ip[i] = ivalue;
 
196
    } else if (strcmp(type,"short") == 0) {
 
197
      short *ip,ivalue;
 
198
      int i;
 
199
      ivalue = (short) SvIV(value);
 
200
      ip = (short *) ptr;
 
201
      for (i = 0; i < numelements; i++)
 
202
        ip[i] = ivalue;
 
203
    } else if (strcmp(type,"long") == 0) {
 
204
      long *ip,ivalue;
 
205
      int i;
 
206
      ivalue = (long) SvIV(value);
 
207
      ip = (long *) ptr;
 
208
      for (i = 0; i < numelements; i++)
 
209
        ip[i] = ivalue;
 
210
    } else if (strcmp(type,"double") == 0) {
 
211
      double *ip,ivalue;
 
212
      int i;
 
213
      ivalue = (double) SvNV(value);
 
214
      ip = (double *) ptr;
 
215
      for (i = 0; i < numelements; i++)
 
216
        ip[i] = ivalue;
 
217
    } else if (strcmp(type,"float") == 0) {
 
218
      float *ip,ivalue;
 
219
      int i;
 
220
      ivalue = (float) SvNV(value);
 
221
      ip = (float *) ptr;
 
222
      for (i = 0; i < numelements; i++)
 
223
        ip[i] = ivalue;
 
224
    } else if (strcmp(type,"char") == 0) {
 
225
      char *ip,*ivalue;
 
226
      ivalue = (char *) SvPV(value,PL_na);
 
227
      ip = (char *) ptr;
 
228
      strncpy(ip,ivalue,numelements-1);
 
229
    } else if (strcmp(type,"char *") == 0) {
 
230
      char **ip, *ivalue;
 
231
      int  i;
 
232
      ivalue = (char *) SvPV(value,PL_na);
 
233
      ip = (char **) ptr;
 
234
      for (i = 0; i < numelements; i++) {
 
235
        if (ivalue) {
 
236
          ip[i] = (char *) malloc(strlen(ivalue)+1);
 
237
          strcpy(ip[i],ivalue);
 
238
        } else {
 
239
          ip[i] = 0;
 
240
        }
 
241
      }
 
242
      ip[numelements] = 0;
 
243
    }
 
244
  } 
 
245
  /* Create the pointer value */
 
246
  
 
247
 
 
248
  obj = sv_newmortal();
 
249
  SWIG_MakePtr(obj,ptr,cast);
 
250
  return obj;
 
251
}
 
252
 
 
253
/*------------------------------------------------------------------
 
254
  ptrset(ptr,value,index = 0,type = 0)
 
255
 
 
256
  Attempts to set the value of a pointer variable.  If type is
 
257
  given, we will use that type.  Otherwise, we'll guess the datatype.
 
258
  ------------------------------------------------------------------ */
 
259
 
 
260
#ifdef PERL_OBJECT
 
261
static void _ptrset(CPerlObj *pPerl,SV *_PTRVALUE, SV *value, int index, const char *type) {
 
262
#define ptrset(a,b,c,d) _ptrset(pPerl,a,b,c,d)
 
263
#else
 
264
static void _ptrset(SV *_PTRVALUE, SV *value, int index, const char *type) {
 
265
#define ptrset(a,b,c,d) _ptrset(a,b,c,d)
 
266
#endif
 
267
  void     *ptr;
 
268
  SV       *obj;
 
269
 
 
270
 
 
271
  if (SWIG_ConvertPtr(_PTRVALUE, &ptr, 0) < 0) {
 
272
    croak("Type error it ptrvalue. Argument is not a valid pointer value.");
 
273
  } else {
 
274
    /* If no datatype was passed, try a few common datatypes first */
 
275
    if (!type) {
 
276
      /* No datatype was passed.   Type to figure out if it's a common one */
 
277
      if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_int_p) >= 0) {
 
278
        type = "int";
 
279
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_double_p) >= 0) {
 
280
        type = "double";
 
281
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_short_p) >= 0) {
 
282
        type = "short";
 
283
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_long_p) >= 0) {
 
284
        type = "long";
 
285
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_float_p) >= 0) {
 
286
        type = "float";
 
287
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_char_p) >= 0) {
 
288
        type = "char";
 
289
      } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_char_pp) >= 0) {
 
290
        type = "char *";
 
291
      } else {
 
292
        type = "unknown";
 
293
      }
 
294
    }
 
295
  }
 
296
  if (!ptr) {
 
297
    croak("Unable to set NULL pointer.");
 
298
    return;
 
299
  }
 
300
  
 
301
  /* Now we have a datatype.  Try to figure out what to do about it */
 
302
  if (strcmp(type,"int") == 0) {
 
303
    *(((int *) ptr)+index) = (int) SvIV(value);
 
304
  } else if (strcmp(type,"double") == 0) {
 
305
    *(((double *) ptr)+index) = (double) SvNV(value);
 
306
  } else if (strcmp(type,"short") == 0) {
 
307
    *(((short *) ptr)+index) = (short) SvIV(value);
 
308
  } else if (strcmp(type,"long") == 0) {
 
309
    *(((long *) ptr)+index) = (long) SvIV(value);
 
310
  } else if (strcmp(type,"float") == 0) {
 
311
    *(((float *) ptr)+index) = (float) SvNV(value);
 
312
  } else if (strcmp(type,"char") == 0) {
 
313
    char *c = SvPV(value,PL_na);
 
314
    strcpy(((char *) ptr)+index, c);
 
315
  } else if (strcmp(type,"char *") == 0) {
 
316
    char *c = SvPV(value,PL_na);
 
317
    char **ca = (char **) ptr;
 
318
    if (ca[index]) free(ca[index]);
 
319
    if (strcmp(c,"NULL") == 0) {
 
320
      ca[index] = 0;
 
321
    } else {
 
322
      ca[index] = (char *) malloc(strlen(c)+1);
 
323
      strcpy(ca[index],c);
 
324
    }
 
325
  } else {
 
326
    croak("Unable to set unsupported datatype.");
 
327
    return;
 
328
  }
 
329
}
 
330
 
 
331
/*------------------------------------------------------------------
 
332
  ptradd(ptr,offset)
 
333
 
 
334
  Adds a value to an existing pointer value.  Will do a type-dependent
 
335
  add for basic datatypes.  For other datatypes, will do a byte-add.
 
336
  ------------------------------------------------------------------ */
 
337
 
 
338
#ifdef PERL_OBJECT
 
339
static SV *_ptradd(CPerlObj *pPerl, SV *_PTRVALUE, int offset) {
 
340
#define ptradd(a,b) _ptradd(pPerl,a,b)
 
341
#else
 
342
static SV *_ptradd(SV *_PTRVALUE, int offset) {
 
343
#define ptradd(a,b) _ptradd(a,b)
 
344
#endif
 
345
 
 
346
  void *ptr,*junk;
 
347
  SV   *obj;
 
348
  swig_type_info *type;
 
349
  char *tname;
 
350
 
 
351
  /* Try to handle a few common datatypes first */
 
352
 
 
353
  if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_int_p) >= 0) {
 
354
    ptr = (void *) (((int *) ptr) + offset);
 
355
  } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_double_p) >= 0) {
 
356
    ptr = (void *) (((double *) ptr) + offset);
 
357
  } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_short_p) >= 0) {
 
358
    ptr = (void *) (((short *) ptr) + offset);
 
359
  } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_long_p) >= 0) {
 
360
    ptr = (void *) (((long *) ptr) + offset);
 
361
  } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_float_p) >= 0) {
 
362
    ptr = (void *) (((float *) ptr) + offset);
 
363
  } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,SWIG_POINTER_char_p) >= 0) {
 
364
    ptr = (void *) (((char *) ptr) + offset);
 
365
  } else if (SWIG_ConvertPtr(_PTRVALUE,&ptr,0) >= 0) {
 
366
    ptr = (void *) (((char *) ptr) + offset);
 
367
  } else {
 
368
    croak("Type error in ptradd. Argument is not a valid pointer value.");
 
369
    return 0;
 
370
  }
 
371
  tname = HvNAME(SvSTASH(SvRV(_PTRVALUE)));
 
372
  obj = sv_newmortal();
 
373
  sv_setref_pv(obj,tname,ptr);
 
374
  return obj;
 
375
}
 
376
 
 
377
/*------------------------------------------------------------------
 
378
  ptrfree(ptr)
 
379
 
 
380
  Destroys a pointer value
 
381
  ------------------------------------------------------------------ */
 
382
#ifdef PERL_OBJECT
 
383
void _ptrfree(CPerlObj *pPerl, SV *_PTRVALUE) {
 
384
#define ptrfree(a) _ptrfree(pPerl, a)
 
385
#else
 
386
void _ptrfree(SV *_PTRVALUE) {
 
387
#define ptrfree(a) _ptrfree(a)
 
388
#endif
 
389
 
 
390
  void *ptr, *junk;
 
391
 
 
392
  if (SWIG_ConvertPtr(_PTRVALUE,&ptr,0) < 0) {
 
393
    croak("Type error in ptrfree. Argument is not a valid pointer value.");
 
394
    return;
 
395
  }
 
396
 
 
397
  /* Check to see if this pointer is a char ** */
 
398
  if (SWIG_ConvertPtr(_PTRVALUE,&junk,SWIG_POINTER_char_pp) >= 0) {
 
399
    char **c = (char **) ptr;
 
400
    if (c) {
 
401
      int i = 0;
 
402
      while (c[i]) {
 
403
        free(c[i]);
 
404
        i++;
 
405
      }
 
406
    }
 
407
  } 
 
408
  if (ptr)
 
409
    free((char *) ptr);
 
410
}
 
411
 
 
412
%}
 
413
 
 
414
%typemap(perl5,in) SV *ptr, SV *value {
 
415
  $1 = $input;
 
416
}
 
417
 
 
418
 
 
419
%typemap(perl5,out) SV *ptrcast,
 
420
                     SV *ptrvalue,
 
421
                     SV *ptrcreate,
 
422
                     SV *ptradd
 
423
{
 
424
  $result = $1;
 
425
  argvi++;
 
426
}
 
427
 
 
428
SV *ptrvalue(SV *ptr, int index = 0, char *type = 0);
 
429
// Returns the value that a pointer is pointing to (ie. dereferencing).
 
430
// The type is automatically inferred by the pointer type--thus, an
 
431
// integer pointer will return an integer, a double will return a double,
 
432
// and so on.   The index and type fields are optional parameters.  When
 
433
// an index is specified, this function returns the value of ptr[index].
 
434
// This allows array access.   When a type is specified, it overrides
 
435
// the given pointer type.   Examples :
 
436
//
 
437
//    ptrvalue($a)             #  Returns the value *a
 
438
//    ptrvalue($a,10)          #  Returns the value a[10]
 
439
//    ptrvalue($a,10,"double") #  Returns a[10] assuming a is a double *
 
440
 
 
441
 
 
442
void ptrset(SV *ptr, SV *value, int index = 0, char *type = 0);
 
443
// Sets the value pointed to by a pointer.  The type is automatically
 
444
// inferred from the pointer type so this function will work for
 
445
// integers, floats, doubles, etc...  The index and type fields are
 
446
// optional.  When an index is given, it provides array access.  When
 
447
// type is specified, it overrides the given pointer type.  Examples :
 
448
// 
 
449
//   ptrset($a,3)            # Sets the value *a = 3
 
450
//   ptrset($a,3,10)         # Sets a[10] = 3
 
451
//   ptrset($a,3,10,"int")   # Sets a[10] = 3 assuming a is a int *
 
452
 
 
453
 
 
454
SV *ptrcreate(char *type, SV *value = 0, int nitems = 1);
 
455
// Creates a new object and returns a pointer to it.  This function 
 
456
// can be used to create various kinds of objects for use in C functions.
 
457
// type specifies the basic C datatype to create and value is an
 
458
// optional parameter that can be used to set the initial value of the
 
459
// object.  nitems is an optional parameter that can be used to create
 
460
// an array.  This function results in a memory allocation using
 
461
// malloc().  Examples :
 
462
//
 
463
//   $a = ptrcreate("double")     # Create a new double, return pointer
 
464
//   $a = ptrcreate("int",7)      # Create an integer, set value to 7
 
465
//   $a = ptrcreate("int",0,1000) # Create an integer array with initial
 
466
//                                # values all set to zero
 
467
//
 
468
// This function only recognizes a few common C datatypes as listed below :
 
469
//
 
470
//        int, short, long, float, double, char, char *, void
 
471
//
 
472
// All other datatypes will result in an error.  However, other
 
473
// datatypes can be created by using the ptrcast function.  For
 
474
// example:
 
475
//
 
476
//  $a = ptrcast(ptrcreate("int",0,100),"unsigned int *")
 
477
 
 
478
 
 
479
void ptrfree(SV *ptr);
 
480
// Destroys the memory pointed to by ptr.  This function calls free()
 
481
// and should only be used with objects created by ptrcreate().  Since
 
482
// this function calls free, it may work with other objects, but this
 
483
// is generally discouraged unless you absolutely know what you're
 
484
// doing.
 
485
 
 
486
SV *ptradd(SV *ptr, int offset);
 
487
// Adds a value to the current pointer value.  For the C datatypes of
 
488
// int, short, long, float, double, and char, the offset value is the
 
489
// number of objects and works in exactly the same manner as in C.  For
 
490
// example, the following code steps through the elements of an array
 
491
//
 
492
//  $a = ptrcreate("double",0,100);    # Create an array double a[100]
 
493
//  $b = $a;
 
494
//  for ($i = 0; $i < 100; $i++) {
 
495
//      ptrset($b,0.0025*$i);          # set *b = 0.0025*i
 
496
//      $b = ptradd($b,1);             # b++ (go to next double)
 
497
//  }
 
498
//
 
499
// In this case, adding one to b goes to the next double.
 
500
// 
 
501
// For all other datatypes (including all complex datatypes), the
 
502
// offset corresponds to bytes.  This function does not perform any
 
503
// bounds checking and negative offsets are perfectly legal.  
 
504
 
 
505
 
 
506