1  /***************************************************************************


2  * _ _ ____ _


3  * Project ___    _ \ 


4  * / __    _)  


5  *  (__ _  _ < ___


6  * \___\___/_ \_\_____


7  *


8  * Copyright (C) 1998  2011, Daniel Stenberg, <daniel@haxx.se>, et al.


9  *


10  * This software is licensed as described in the file COPYING, which


11  * you should have received as part of this distribution. The terms


12  * are also available at https://curl.haxx.se/docs/copyright.html.


13  *


14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell


15  * copies of the Software, and permit persons to whom the Software is


16  * furnished to do so, under the terms of the COPYING file.


17  *


18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY


19  * KIND, either express or implied.


20  *


21  ***************************************************************************/


22 


23  #include "curl_setup.h"


24 


25  #include "strtoofft.h"


26 


27  /*


28  * NOTE:


29  *


30  * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we


31  * could use in case strtoll() doesn't exist... See


32  * http://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html


33  */


34 


35  #ifdef NEED_CURL_STRTOLL


36 


37  /* Range tests can be used for alphanum decoding if characters are consecutive,


38  like in ASCII. Else an array is scanned. Determine this condition now. */


39 


40  #if('9'  '0') != 9  ('Z'  'A') != 25  ('z'  'a') != 25


41 


42  #define NO_RANGE_TEST


43 


44  static const char valchars[] =


45  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";


46  #endif


47 


48  static int get_char(char c, int base);


49 


50  /**


51  * Emulated version of the strtoll function. This extracts a long long


52  * value from the given input string and returns it.


53  */


54  curl_off_t


55  curlx_strtoll(const char *nptr, char **endptr, int base)


56  {


57  char *end;


58  int is_negative = 0;


59  int overflow;


60  int i;


61  curl_off_t value = 0;


62  curl_off_t newval;


63 


64  /* Skip leading whitespace. */


65  end = (char *)nptr;


66  while(ISSPACE(end[0])) {


67  end++;


68  }


69 


70  /* Handle the sign, if any. */


71  if(end[0] == '') {


72  is_negative = 1;


73  end++;


74  }


75  else if(end[0] == '+') {


76  end++;


77  }


78  else if(end[0] == '\0') {


79  /* We had nothing but perhaps some whitespace  there was no number. */


80  if(endptr) {


81  *endptr = end;


82  }


83  return 0;


84  }


85 


86  /* Handle special beginnings, if present and allowed. */


87  if(end[0] == '0' && end[1] == 'x') {


88  if(base == 16  base == 0) {


89  end += 2;


90  base = 16;


91  }


92  }


93  else if(end[0] == '0') {


94  if(base == 8  base == 0) {


95  end++;


96  base = 8;


97  }


98  }


99 


100  /* Matching strtol, if the base is 0 and it doesn't look like


101  * the number is octal or hex, we assume it's base 10.


102  */


103  if(base == 0) {


104  base = 10;


105  }


106 


107  /* Loop handling digits. */


108  value = 0;


109  overflow = 0;


110  for(i = get_char(end[0], base);


111  i != 1;


112  end++, i = get_char(end[0], base)) {


113  newval = base * value + i;


114  if(newval < value) {


115  /* We've overflowed. */


116  overflow = 1;


117  break;


118  }


119  else


120  value = newval;


121  }


122 


123  if(!overflow) {


124  if(is_negative) {


125  /* Fix the sign. */


126  value *= 1;


127  }


128  }


129  else {


130  if(is_negative)


131  value = CURL_OFF_T_MIN;


132  else


133  value = CURL_OFF_T_MAX;


134 


135  SET_ERRNO(ERANGE);


136  }


137 


138  if(endptr)


139  *endptr = end;


140 


141  return value;


142  }


143 


144  /**


145  * Returns the value of c in the given base, or 1 if c cannot


146  * be interpreted properly in that base (i.e., is out of range,


147  * is a null, etc.).


148  *


149  * @param c the character to interpret according to base


150  * @param base the base in which to interpret c


151  *


152  * @return the value of c in base, or 1 if c isn't in range


153  */


154  static int get_char(char c, int base)


155  {


156  #ifndef NO_RANGE_TEST


157  int value = 1;


158  if(c <= '9' && c >= '0') {


159  value = c  '0';


160  }


161  else if(c <= 'Z' && c >= 'A') {


162  value = c  'A' + 10;


163  }


164  else if(c <= 'z' && c >= 'a') {


165  value = c  'a' + 10;


166  }


167  #else


168  const char * cp;


169  int value;


170 


171  cp = memchr(valchars, c, 10 + 26 + 26);


172 


173  if(!cp)


174  return 1;


175 


176  value = cp  valchars;


177 


178  if(value >= 10 + 26)


179  value = 26; /* Lowercase. */


180  #endif


181 


182  if(value >= base) {


183  value = 1;


184  }


185 


186  return value;


187  }


188  #endif /* Only present if we need strtoll, but don't have it. */

