Hi,

Did you find anything wrong with this patch? Please let me know if it needs
corrections.

Thanks !

Best Regards,

Abbas Raza

On 1 September 2016 at 14:45, Abbas Raza <abbas.raza.1...@gmail.com> wrote:

> Signed-off-by: Abbas Raza <abbas.raza.1...@gmail.com>
> ---
>  Headers/Foundation/NSScanner.h |   3 +-
>  Source/NSScanner.m             | 143 ++++++++++++++++++++++++++++++
> +++++++++--
>  Tests/base/NSScanner/test01.m  |  17 +++++
>  3 files changed, 157 insertions(+), 6 deletions(-)
>
> diff --git a/Headers/Foundation/NSScanner.h b/Headers/Foundation/NSScanner
> .h
> index a3b61dd..b103642 100644
> --- a/Headers/Foundation/NSScanner.h
> +++ b/Headers/Foundation/NSScanner.h
> @@ -94,6 +94,7 @@ extern "C" {
>  - (BOOL) scanInt: (int*)value;
>  - (BOOL) scanHexInt: (unsigned int*)value;
>  - (BOOL) scanLongLong: (long long*)value;
> +- (BOOL) scanHexLongLong: (unsigned long long*)value;
>  - (BOOL) scanFloat: (float*)value;
>  - (BOOL) scanDouble: (double*)value;
>  - (BOOL) scanString: (NSString*)string intoString: (NSString**)value;
> @@ -116,8 +117,6 @@ extern "C" {
>  /** Not implemented */
>  - (BOOL) scanHexFloat: (float *)result;
>  /** Not implemented */
> -- (BOOL) scanHexLongLong: (unsigned long long *)result;
> -/** Not implemented */
>  - (BOOL) scanInteger: (NSInteger *)value;
>  #endif
>  @end
> diff --git a/Source/NSScanner.m b/Source/NSScanner.m
> index 26c3077..149be49 100644
> --- a/Source/NSScanner.m
> +++ b/Source/NSScanner.m
> @@ -629,6 +629,145 @@ typedef GSString  *ivars;
>  #endif /* defined(LLONG_MAX) */
>  }
>
> +/*
> + * Scan an unsigned long long of the given radix into value.
> + * Internal version used by scanHexLongLong: .
> + */
> +- (BOOL) scanUnsignedLongLong_: (unsigned long long int*)value
> +                   radix: (NSUInteger)radix
> +               gotDigits: (BOOL)gotDigits
> +{
> +#if defined(ULLONG_MAX)
> +  unsigned long long int       num = 0;
> +  unsigned long long int       numLimit, digitLimit, digitValue;
> +  BOOL         overflow = NO;
> +  unsigned int saveScanLocation = _scanLocation;
> +
> +  /* Set limits */
> +  numLimit = ULLONG_MAX / radix;
> +  digitLimit = ULLONG_MAX % radix;
> +
> +  /* Process digits */
> +  while (_scanLocation < myLength())
> +    {
> +      unichar digit = myCharacter(_scanLocation);
> +
> +      switch (digit)
> +       {
> +         case '0': digitValue = 0; break;
> +         case '1': digitValue = 1; break;
> +         case '2': digitValue = 2; break;
> +         case '3': digitValue = 3; break;
> +         case '4': digitValue = 4; break;
> +         case '5': digitValue = 5; break;
> +         case '6': digitValue = 6; break;
> +         case '7': digitValue = 7; break;
> +         case '8': digitValue = 8; break;
> +         case '9': digitValue = 9; break;
> +         case 'a': digitValue = 0xA; break;
> +         case 'b': digitValue = 0xB; break;
> +         case 'c': digitValue = 0xC; break;
> +         case 'd': digitValue = 0xD; break;
> +         case 'e': digitValue = 0xE; break;
> +         case 'f': digitValue = 0xF; break;
> +         case 'A': digitValue = 0xA; break;
> +         case 'B': digitValue = 0xB; break;
> +         case 'C': digitValue = 0xC; break;
> +         case 'D': digitValue = 0xD; break;
> +         case 'E': digitValue = 0xE; break;
> +         case 'F': digitValue = 0xF; break;
> +         default:
> +           digitValue = radix;
> +           break;
> +       }
> +      if (digitValue >= radix)
> +       break;
> +      if (!overflow)
> +       {
> +         if ((num > numLimit)
> +           || ((num == numLimit) && (digitValue > digitLimit)))
> +           overflow = YES;
> +         else
> +           num = num * radix + digitValue;
> +       }
> +      _scanLocation++;
> +      gotDigits = YES;
> +    }
> +
> +  /* Save result */
> +  if (!gotDigits)
> +    {
> +      _scanLocation = saveScanLocation;
> +      return NO;
> +    }
> +  if (value)
> +    {
> +      if (overflow)
> +       *value = ULLONG_MAX;
> +      else
> +       *value = num;
> +    }
> +  return YES;
> +#else /* defined(ULLONG_MAX) */
> +  /*
> +   * Provide compile-time warning and run-time exception.
> +   */
> +#    warning "Can't use unsigned long long variables."
> +  [NSException raise: NSGenericException
> +              format: @"Can't use unsigned long long variables."];
> +  return NO;
> +#endif /* defined(ULLONG_MAX) */
> +}
> +
> +/**
> + * After initial skipping (if any), this method scans a hexadecimal
> + * long long value (optionally prefixed by "0x" or "0X"),
> + * placing it in <em>longLongValue</em> if that is not null.
> + * <br/>
> + * Returns YES if anything is scanned, NO otherwise.
> + * <br/>
> + * On overflow, ULLONG_MAX or ULLONG_MAX is put into
> <em>longLongValue</em>
> + * <br/>
> + * Scans past any excess digits
> + */
> +- (BOOL) scanHexLongLong: (unsigned long long*)value
> +{
> +  unsigned int saveScanLocation = _scanLocation;
> +
> +  /* Skip whitespace */
> +  if (!skipToNextField())
> +    {
> +      _scanLocation = saveScanLocation;
> +      return NO;
> +    }
> +
> +  if ((_scanLocation < myLength()) && (myCharacter(_scanLocation) == '0'))
> +    {
> +      _scanLocation++;
> +      if (_scanLocation < myLength())
> +       {
> +         switch (myCharacter(_scanLocation))
> +           {
> +             case 'x':
> +             case 'X':
> +               _scanLocation++;        // Scan beyond the 0x prefix
> +               break;
> +             default:
> +               _scanLocation--;        // Scan from the initial digit
> +               break;
> +           }
> +       }
> +      else
> +       {
> +         _scanLocation--;      // Just scan the zero.
> +       }
> +    }
> +  if ([self scanUnsignedLongLong_: value radix: 16 gotDigits: NO])
> +    return YES;
> +  _scanLocation = saveScanLocation;
> +  return NO;
> +}
> +
>  /**
>   * Not implemented.
>   */
> @@ -1140,10 +1279,6 @@ typedef GSString *ivars;
>  {
>    return NO;    // FIXME
>  }
> -- (BOOL) scanHexLongLong: (unsigned long long *)result
> -{
> -  return NO;    // FIXME
> -}
>  - (BOOL) scanInteger: (NSInteger *)value
>  {
>  #if GS_SIZEOF_VOIDP == GS_SIZEOF_INT
> diff --git a/Tests/base/NSScanner/test01.m b/Tests/base/NSScanner/test01.m
> index 63dd912..13cc29e 100644
> --- a/Tests/base/NSScanner/test01.m
> +++ b/Tests/base/NSScanner/test01.m
> @@ -51,6 +51,19 @@ static BOOL scanHex(NSString *str,
>    return ((expectValue == 1) ? (expectedValue == *retp) : YES
>            && expectedScanLoc == [scn scanLocation]);
>  }
> +
> +static BOOL scanHexLongLong(NSString *str,
> +                   int expectValue,
> +                   unsigned long long expectedValue,
> +                   int expectedScanLoc,
> +                   int *retp)
> +{
> +  NSScanner *scn = [NSScanner scannerWithString:str];
> +  [scn scanHexLongLong:retp];
> +  return ((expectValue == 1) ? (expectedValue == *retp) : YES
> +          && expectedScanLoc == [scn scanLocation]);
> +}
> +
>  static BOOL scanDouble(NSString *str,
>                     double expectedValue,
>                     double *retp)
> @@ -104,6 +117,10 @@ int main()
>    PASS(scanHex(@"1234FOO", 1, 0x1234F, 5, &ret)
>         && scanHex(@"01234FOO", 1, 0x1234F, 6, &ret),
>         "NSScanner hex (non-digits terminate scan)");
> +
> +  PASS(scanHexLongLong(@"1234FOO", 1, 0x1234F, 5, &ret)
> +       && scanHexLongLong(@"01234FOO", 1, 0x1234F, 6, &ret),
> +       "NSScanner hex long long (non-digits terminate scan)");
>   /* dbl1 = 123.456;
>    dbl2 = 123.45678901234567890123456789012345678901234567;
>    dbl3 = 1.23456789;
> --
> 2.1.4
>
>
>
_______________________________________________
Bug-gnustep mailing list
Bug-gnustep@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-gnustep

Reply via email to