File: GSValue.m

package info (click to toggle)
gnustep-base 1.28.1%2Breally1.28.0-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 28,008 kB
  • sloc: objc: 223,137; ansic: 35,562; sh: 184; makefile: 128; cpp: 122; xml: 32
file content (279 lines) | stat: -rw-r--r-- 6,613 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/** GSValue - Object encapsulation for C types.
   Copyright (C) 1993,1994,1995,1999 Free Software Foundation, Inc.

   Written by:  Adam Fedor <fedor@boulder.colorado.edu>
   Date: Mar 1995

   This file is part of the GNUstep Base Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110 USA.
*/

#import "common.h"
#import "Foundation/NSValue.h"
#import "Foundation/NSData.h"
#import "Foundation/NSException.h"
#import "Foundation/NSCoder.h"

@interface GSValue : NSValue
{
  void *data;
  char *objctype;
}
@end

/* This is the real, general purpose value object.  I've implemented all the
   methods here (like pointValue) even though most likely, other concrete
   subclasses were created to handle these types */

@implementation GSValue

static inline unsigned
typeSize(const char* type)
{
  switch (*type)
    {
      case _C_ID:	return sizeof(id);
      case _C_CLASS:	return sizeof(Class);
      case _C_SEL:	return sizeof(SEL);
      case _C_CHR:	return sizeof(char);
      case _C_UCHR:	return sizeof(unsigned char);
      case _C_SHT:	return sizeof(short);
      case _C_USHT:	return sizeof(unsigned short);
      case _C_INT:	return sizeof(int);
      case _C_UINT:	return sizeof(unsigned int);
      case _C_LNG:	return sizeof(long);
      case _C_ULNG:	return sizeof(unsigned long);
      case _C_LNG_LNG:	return sizeof(long long);
      case _C_ULNG_LNG:	return sizeof(unsigned long long);
      case _C_FLT:	return sizeof(float);
      case _C_DBL:	return sizeof(double);
#if __GNUC__ > 2 && defined(_C_BOOL)
      case _C_BOOL:	return sizeof(_Bool);
#endif
      case _C_PTR:	return sizeof(void*);
      case _C_CHARPTR:	return sizeof(char*);
      case _C_BFLD:
      case _C_ARY_B:
      case _C_UNION_B:
      case _C_STRUCT_B:
	{
	  NSUInteger	size;

	  NSGetSizeAndAlignment(type, &size, 0);
	  return (int)size;
	}
      case _C_VOID:	return 0;
      default:		return 0;
    }
}

// Allocating and Initializing

- (id) initWithBytes: (const void *)value
	    objCType: (const char *)type
{
  if (!value || !type)
    {
      NSLog(@"Tried to create NSValue with NULL value or NULL type");
      DESTROY(self);
      return nil;
    }

  self = [super init];
  if (self != nil)
    {
      unsigned	size = typeSize(type);

      if (size > 0)
	{
	  data = (void *)NSZoneMalloc([self zone], size);
	  memcpy(data, value, size);
	}
      else
        {
	  NSLog(@"Tried to create NSValue with invalid Objective-C type");
	  DESTROY(self);
	  return nil;
        }
      size = strlen(type);
      objctype = (char *)NSZoneMalloc([self zone], size + 1);
      memcpy(objctype, type, size);
      objctype[size] = '\0';
    }
  return self;
}

- (void) dealloc
{
  if (objctype != 0)
    NSZoneFree([self zone], objctype);
  if (data != 0)
    NSZoneFree([self zone], data);
  [super dealloc];
}

// Accessing Data
- (void) getValue: (void *)value
{
  unsigned	size;

  size = typeSize(objctype);
  if (size > 0)
    {
      if (value == 0)
	{
	  [NSException raise: NSInvalidArgumentException
		      format: @"Cannot copy value into NULL buffer"];
	  /* NOT REACHED */
	}
      memcpy(value, data, size);
    }
}

- (NSUInteger) hash
{
  unsigned	size = typeSize(objctype);
  unsigned	hash = 0;

  while (size-- > 0)
    {
      hash += ((unsigned char*)data)[size];
    }
  return hash;
}

- (BOOL) isEqualToValue: (NSValue*)aValue
{
  if (aValue == self)
    {
      return YES;
    }
  if (aValue == nil)
    {
      return NO;
    }
  if (object_getClass(aValue) != object_getClass(self))
    {
      return NO;
    }
  if (!GSSelectorTypesMatch(objctype, ((GSValue*)aValue)->objctype))
    {
      return NO;
    }
  if (memcmp(((GSValue*)aValue)->data, data, typeSize(objctype)) != 0)
    {
      return NO;
    }
  return YES;
}

- (const char *)objCType
{
  return objctype;
}

- (id) nonretainedObjectValue
{
  unsigned	size = typeSize(objctype);

  if (size != sizeof(void*))
    {
      [NSException raise: NSInternalInconsistencyException
		  format: @"Return value of size %u as object", size];
    }
  return *((id *)data);
}

- (NSPoint) pointValue
{
  unsigned	size = typeSize(objctype);

  if (size != sizeof(NSPoint))
    {
      [NSException raise: NSInternalInconsistencyException
		  format: @"Return value of size %u as NSPoint", size];
    }
  return *((NSPoint *)data);
}

- (void *) pointerValue
{
  unsigned	size = typeSize(objctype);

  if (size != sizeof(void*))
    {
      [NSException raise: NSInternalInconsistencyException
		  format: @"Return value of size %u as pointer", size];
    }
  return *((void **)data);
}

- (NSRect) rectValue
{
  unsigned	size = (unsigned)typeSize(objctype);

  if (size != sizeof(NSRect))
    {
      [NSException raise: NSInternalInconsistencyException
		  format: @"Return value of size %u as NSRect", size];
    }
  return *((NSRect *)data);
}

- (NSSize) sizeValue
{
  unsigned	size = typeSize(objctype);

  if (size != sizeof(NSSize))
    {
      [NSException raise: NSInternalInconsistencyException
		  format: @"Return value of size %u as NSSize", size];
    }
  return *((NSSize *)data);
}

- (NSString *) description
{
  unsigned	size;
  NSData	*rep;

  size = typeSize(objctype);
  rep = [NSData dataWithBytes: data length: size];
  return [NSString stringWithFormat: @"(%s) %@", objctype, [rep description]];
}

- (void) encodeWithCoder: (NSCoder *)coder
{
  NSUInteger	tsize;
  unsigned	size;
  NSMutableData	*d;

  size = strlen(objctype)+1;
  [coder encodeValueOfObjCType: @encode(unsigned) at: &size];
  [coder encodeArrayOfObjCType: @encode(signed char) count: size at: objctype];
  NSGetSizeAndAlignment(objctype, 0, &tsize);
  size = tsize;
  d = [NSMutableData new];
  [d serializeDataAt: data ofObjCType: objctype context: nil];
  size = [d length];
  [coder encodeValueOfObjCType: @encode(unsigned) at: &size];
  [coder encodeArrayOfObjCType: @encode(unsigned char)
			 count: size
			    at: [d bytes]];
  RELEASE(d);
}
@end