1 /*
2 * Copyright (C) 1995,1999 Free Software Foundation, Inc.
3 *
4 * Written by: Adam Fedor <fedor@boulder.colorado.edu>
5 * Date: 1995
6 *
7 * This file is part of the GNUstep Base Library.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02111 USA.
23 */
24
25 #ifndef __NSRange_h_GNUSTEP_BASE_INCLUDE
26 #define __NSRange_h_GNUSTEP_BASE_INCLUDE
27 #import "../GNUstepBase/GSVersionMacros.h"
28
29 /**** Included Headers *******************************************************/
30
31 #import "NSObject.h"
32
33 #if defined(__cplusplus)
34 extern "C" {
35 #endif
36
37 @class NSException;
38 @class NXConstantString;
39
40 /**** Type, Constant, and Macro Definitions **********************************/
41
42 #ifndef MAX
43 #define MAX(a,b) \
44 ({__typeof__(a) _MAX_a = (a); __typeof__(b) _MAX_b = (b); \
45 _MAX_a > _MAX_b ? _MAX_a : _MAX_b; })
46 #define GS_DEFINED_MAX
47 #endif
48
49 #ifndef MIN
50 #define MIN(a,b) \
51 ({__typeof__(a) _MIN_a = (a); __typeof__(b) _MIN_b = (b); \
52 _MIN_a < _MIN_b ? _MIN_a : _MIN_b; })
53 #define GS_DEFINED_MIN
54 #endif
55
56 /**
57 * <example>
58 {
59 NSUInteger location;
60 NSUInteger length;
61 }</example>
62 * <p>
63 * The NSRange type is used to specify ranges of locations,
64 * typically items in an array, characters in a string, and bytes
65 * in a data object.
66 * </p>
67 * <p>
68 * As 'boundary' or 'fencepost' errors are a particularly common
69 * problem in programming, it is important that you understand
70 * how an NSRange works.
71 * </p>
72 * <p>
73 * An NSRange consists of a <em>location</em> and a <em>length</em>. The
74 * points that are considered to lie in a range are the integers from
75 * the location to the location plus the length, so the number
76 * of points in a range is the length of the range plus one.<br />
77 * However, if you consider these points like the marks on a
78 * ruler, you can only store information <strong>between</strong>
79 * points. So the number of items that can be stored in a range
80 * is the length of the range.
81 * </p>
82 */
83 typedef struct _NSRange NSRange;
84 struct _NSRange
85 {
86 NSUInteger location;
87 NSUInteger length;
88 };
89
90 #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
91 /** Pointer to an NSRange structure. */
92 typedef NSRange *NSRangePointer;
93 #endif
94
95 /**** Function Prototypes ****************************************************/
96
97 /*
98 * All but the most complex functions are declared static inline in this
99 * header file so that they are maximally efficient. In order to provide
100 * true functions (for code modules that don't have this header) this
101 * header is included in NSRange.m where the functions are no longer
102 * declared inline.
103 */
104 #ifdef IN_NSRANGE_M
105 #define GS_RANGE_SCOPE extern
106 #define GS_RANGE_ATTR
107 #else
108 #define GS_RANGE_SCOPE static inline
109 #define GS_RANGE_ATTR __attribute__((unused))
110 #endif
111
112 GS_RANGE_SCOPE NSUInteger
113 NSMaxRange(NSRange range) GS_RANGE_ATTR;
114
115 /** Returns top end of range (location + length). */
116 GS_RANGE_SCOPE NSUInteger
NSMaxRange(NSRange range)117 NSMaxRange(NSRange range)
118 {
119 return range.location + range.length;
120 }
121
122 GS_RANGE_SCOPE BOOL
123 NSLocationInRange(NSUInteger location, NSRange range) GS_RANGE_ATTR;
124
125 /** Returns whether location is greater than or equal to range's location
126 * and less than its max.
127 */
128 GS_RANGE_SCOPE BOOL
NSLocationInRange(NSUInteger location,NSRange range)129 NSLocationInRange(NSUInteger location, NSRange range)
130 {
131 return (location >= range.location) && (location < NSMaxRange(range));
132 }
133
134 /** Convenience method for raising an NSRangeException. */
135 GS_EXPORT void _NSRangeExceptionRaise (void);
136 /* NB: The implementation of _NSRangeExceptionRaise is:
137 [NSException raise: NSRangeException
138 format: @"Range location + length too great"];
139
140 _NSRangeExceptionRaise is defined in NSRange.m so that this
141 file (NSRange.h) can be included without problems in the
142 implementation of the base classes themselves. */
143
144 GS_RANGE_SCOPE NSRange
145 NSMakeRange(NSUInteger location, NSUInteger length) GS_RANGE_ATTR;
146
147 /** Creates new range starting at location and of given length. */
148 GS_RANGE_SCOPE NSRange
NSMakeRange(NSUInteger location,NSUInteger length)149 NSMakeRange(NSUInteger location, NSUInteger length)
150 {
151 NSRange range;
152 NSUInteger end = location + length;
153
154 if (end < location || end < length)
155 {
156 _NSRangeExceptionRaise ();
157 }
158 range.location = location;
159 range.length = length;
160 return range;
161 }
162
163 GS_RANGE_SCOPE BOOL
164 NSEqualRanges(NSRange range1, NSRange range2) GS_RANGE_ATTR;
165
166 /** Returns whether range1 and range2 have same location and length. */
167 GS_RANGE_SCOPE BOOL
NSEqualRanges(NSRange range1,NSRange range2)168 NSEqualRanges(NSRange range1, NSRange range2)
169 {
170 return ((range1.location == range2.location)
171 && (range1.length == range2.length));
172 }
173
174 GS_RANGE_SCOPE NSRange
175 NSUnionRange(NSRange range1, NSRange range2) GS_RANGE_ATTR;
176
177 /** Returns range going from minimum of aRange's and bRange's locations to
178 maximum of their two max's. */
179 GS_RANGE_SCOPE NSRange
NSUnionRange(NSRange aRange,NSRange bRange)180 NSUnionRange(NSRange aRange, NSRange bRange)
181 {
182 NSRange range;
183
184 range.location = MIN(aRange.location, bRange.location);
185 range.length = MAX(NSMaxRange(aRange), NSMaxRange(bRange))
186 - range.location;
187 return range;
188 }
189
190 GS_RANGE_SCOPE NSRange
191 NSIntersectionRange(NSRange range1, NSRange range2) GS_RANGE_ATTR;
192
193 /** Returns range containing indices existing in both aRange and bRange. If
194 * the returned length is 0, the location is undefined and should be ignored.
195 */
196 GS_RANGE_SCOPE NSRange
NSIntersectionRange(NSRange aRange,NSRange bRange)197 NSIntersectionRange (NSRange aRange, NSRange bRange)
198 {
199 NSRange range;
200
201 if (NSMaxRange(aRange) < bRange.location
202 || NSMaxRange(bRange) < aRange.location)
203 return NSMakeRange(0, 0);
204
205 range.location = MAX(aRange.location, bRange.location);
206 range.length = MIN(NSMaxRange(aRange), NSMaxRange(bRange))
207 - range.location;
208 return range;
209 }
210
211
212 @class NSString;
213
214 /** Returns string of form {location=a, length=b}. */
215 GS_EXPORT NSString *NSStringFromRange(NSRange range);
216
217 /** Parses range from string of form {location=a, length=b}; returns range
218 with 0 location and length if this fails. */
219 GS_EXPORT NSRange NSRangeFromString(NSString *aString);
220
221 #ifdef GS_DEFINED_MAX
222 #undef GS_DEFINED_MAX
223 #undef MAX
224 #endif
225
226 #ifdef GS_DEFINED_MIN
227 #undef GS_DEFINED_MIN
228 #undef MIN
229 #endif
230
231 #if defined(__cplusplus)
232 }
233 #endif
234
235 #endif /* __NSRange_h_GNUSTEP_BASE_INCLUDE */
236