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