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
     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 
     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
     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
     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
     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
     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 */