| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  | /* stringlib: locale related helpers implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <locale.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  | #ifndef STRINGLIB_IS_UNICODE
 | 
					
						
							|  |  |  | #   error "localeutil is specific to Unicode"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     const char *grouping; | 
					
						
							|  |  |  |     char previous; | 
					
						
							|  |  |  |     Py_ssize_t i; /* Where we're currently pointing in grouping. */ | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | } STRINGLIB(GroupGenerator); | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(GroupGenerator_init)(STRINGLIB(GroupGenerator) *self, const char *grouping) | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     self->grouping = grouping; | 
					
						
							|  |  |  |     self->i = 0; | 
					
						
							|  |  |  |     self->previous = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Returns the next grouping, or 0 to signify end. */ | 
					
						
							|  |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(GroupGenerator_next)(STRINGLIB(GroupGenerator) *self) | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     /* Note that we don't really do much error checking here. If a
 | 
					
						
							|  |  |  |        grouping string contains just CHAR_MAX, for example, then just | 
					
						
							|  |  |  |        terminate the generator. That shouldn't happen, but at least we | 
					
						
							|  |  |  |        fail gracefully. */ | 
					
						
							|  |  |  |     switch (self->grouping[self->i]) { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |         return self->previous; | 
					
						
							|  |  |  |     case CHAR_MAX: | 
					
						
							|  |  |  |         /* Stop the generator. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         char ch = self->grouping[self->i]; | 
					
						
							|  |  |  |         self->previous = ch; | 
					
						
							|  |  |  |         self->i++; | 
					
						
							|  |  |  |         return (Py_ssize_t)ch; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Fill in some digits, leading zeros, and thousands separator. All
 | 
					
						
							|  |  |  |    are optional, depending on when we're called. */ | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end, | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  |      Py_ssize_t n_chars, Py_ssize_t n_zeros, STRINGLIB_CHAR* thousands_sep, | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |      Py_ssize_t thousands_sep_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (thousands_sep) { | 
					
						
							|  |  |  |         *buffer_end -= thousands_sep_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Copy the thousands_sep chars into the buffer. */ | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  |         memcpy(*buffer_end, thousands_sep, | 
					
						
							|  |  |  |                thousands_sep_len * STRINGLIB_SIZEOF_CHAR); | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *buffer_end -= n_chars; | 
					
						
							|  |  |  |     *digits_end -= n_chars; | 
					
						
							|  |  |  |     memcpy(*buffer_end, *digits_end, n_chars * sizeof(STRINGLIB_CHAR)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *buffer_end -= n_zeros; | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |     for (i = 0; i < n_zeros; i++) | 
					
						
							|  |  |  |         (*buffer_end)[i] = '0'; | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  |  * InsertThousandsGrouping: | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  |  * @buffer: A pointer to the start of a string. | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |  * @n_buffer: Number of characters in @buffer. | 
					
						
							|  |  |  |  * @digits: A pointer to the digits we're reading from. If count | 
					
						
							|  |  |  |  *          is non-NULL, this is unused. | 
					
						
							| 
									
										
										
										
											2008-06-24 01:06:47 +00:00
										 |  |  |  * @n_digits: The number of digits in the string, in which we want | 
					
						
							|  |  |  |  *            to put the grouping chars. | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |  * @min_width: The minimum width of the digits in the output string. | 
					
						
							|  |  |  |  *             Output will be zero-padded on the left to fill. | 
					
						
							| 
									
										
										
										
											2009-04-03 14:45:06 +00:00
										 |  |  |  * @grouping: see definition in localeconv(). | 
					
						
							|  |  |  |  * @thousands_sep: see definition in localeconv(). | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |  * There are 2 modes: counting and filling. If @buffer is NULL, | 
					
						
							|  |  |  |  *  we are in counting mode, else filling mode. | 
					
						
							|  |  |  |  * If counting, the required buffer size is returned. | 
					
						
							|  |  |  |  * If filling, we know the buffer will be large enough, so we don't | 
					
						
							|  |  |  |  *  need to pass in the buffer size. | 
					
						
							| 
									
										
										
										
											2009-04-03 14:45:06 +00:00
										 |  |  |  * Inserts thousand grouping characters (as defined by grouping and | 
					
						
							|  |  |  |  *  thousands_sep) into the string between buffer and buffer+n_digits. | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Return value: 0 on error, else 1.  Note that no error can occur if | 
					
						
							|  |  |  |  *  count is non-NULL. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This name won't be used, the includer of this file should define | 
					
						
							|  |  |  |  *  it to be the actual function name, based on unicode or string. | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * As closely as possible, this code mimics the logic in decimal.py's | 
					
						
							|  |  |  |     _insert_thousands_sep(). | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  |  **/ | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | Py_ssize_t | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  | STRINGLIB(InsertThousandsGrouping)( | 
					
						
							|  |  |  |     STRINGLIB_CHAR *buffer, | 
					
						
							|  |  |  |     Py_ssize_t n_buffer, | 
					
						
							|  |  |  |     STRINGLIB_CHAR *digits, | 
					
						
							|  |  |  |     Py_ssize_t n_digits, | 
					
						
							|  |  |  |     Py_ssize_t min_width, | 
					
						
							|  |  |  |     const char *grouping, | 
					
						
							|  |  |  |     STRINGLIB_CHAR *thousands_sep, | 
					
						
							|  |  |  |     Py_ssize_t thousands_sep_len) | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |     Py_ssize_t count = 0; | 
					
						
							|  |  |  |     Py_ssize_t n_zeros; | 
					
						
							|  |  |  |     int loop_broken = 0; | 
					
						
							|  |  |  |     int use_separator = 0; /* First time through, don't append the
 | 
					
						
							|  |  |  |                               separator. They only go between | 
					
						
							|  |  |  |                               groups. */ | 
					
						
							|  |  |  |     STRINGLIB_CHAR *buffer_end = NULL; | 
					
						
							|  |  |  |     STRINGLIB_CHAR *digits_end = NULL; | 
					
						
							|  |  |  |     Py_ssize_t l; | 
					
						
							|  |  |  |     Py_ssize_t n_chars; | 
					
						
							|  |  |  |     Py_ssize_t remaining = n_digits; /* Number of chars remaining to
 | 
					
						
							|  |  |  |                                         be looked at */ | 
					
						
							|  |  |  |     /* A generator that returns all of the grouping widths, until it
 | 
					
						
							|  |  |  |        returns 0. */ | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |     STRINGLIB(GroupGenerator) groupgen; | 
					
						
							|  |  |  |     STRINGLIB(GroupGenerator_init)(&groupgen, grouping); | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (buffer) { | 
					
						
							|  |  |  |         buffer_end = buffer + n_buffer; | 
					
						
							|  |  |  |         digits_end = digits + n_digits; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |     while ((l = STRINGLIB(GroupGenerator_next)(&groupgen)) > 0) { | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  |         l = Py_MIN(l, Py_MAX(Py_MAX(remaining, min_width), 1)); | 
					
						
							|  |  |  |         n_zeros = Py_MAX(0, l - remaining); | 
					
						
							|  |  |  |         n_chars = Py_MAX(0, Py_MIN(remaining, l)); | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* Use n_zero zero's and n_chars chars */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Count only, don't do anything. */ | 
					
						
							|  |  |  |         count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (buffer) { | 
					
						
							|  |  |  |             /* Copy into the output buffer. */ | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |             STRINGLIB(fill)(&digits_end, &buffer_end, n_chars, n_zeros, | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |                  use_separator ? thousands_sep : NULL, thousands_sep_len); | 
					
						
							| 
									
										
										
										
											2009-04-03 14:45:06 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
											
												Merged revisions 63078 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
When forward porting this, I added _PyUnicode_InsertThousandsGrouping.
........
  r63078 | eric.smith | 2008-05-11 15:52:48 -0400 (Sun, 11 May 2008) | 14 lines
  Addresses issue 2802: 'n' formatting for integers.
  Adds 'n' as a format specifier for integers, to mirror the same
  specifier which is already available for floats.  'n' is the same as
  'd', but inserts the current locale-specific thousands grouping.
  I added this as a stringlib function, but it's only used by str type,
  not unicode.  This is because of an implementation detail in
  unicode.format(), which does its own str->unicode conversion.  But the
  unicode version will be needed in 3.0, and it may be needed by other
  code eventually in 2.6 (maybe decimal?), so I left it as a stringlib
  implementation.  As long as the unicode version isn't instantiated,
  there's no overhead for this.
........
											
										 
											2008-05-11 21:00:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |         /* Use a separator next time. */ | 
					
						
							|  |  |  |         use_separator = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         remaining -= n_chars; | 
					
						
							|  |  |  |         min_width -= l; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (remaining <= 0 && min_width <= 0) { | 
					
						
							|  |  |  |             loop_broken = 1; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-04-03 14:45:06 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |         min_width -= thousands_sep_len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!loop_broken) { | 
					
						
							|  |  |  |         /* We left the loop without using a break statement. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-24 00:37:51 +01:00
										 |  |  |         l = Py_MAX(Py_MAX(remaining, min_width), 1); | 
					
						
							|  |  |  |         n_zeros = Py_MAX(0, l - remaining); | 
					
						
							|  |  |  |         n_chars = Py_MAX(0, Py_MIN(remaining, l)); | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* Use n_zero zero's and n_chars chars */ | 
					
						
							|  |  |  |         count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars; | 
					
						
							|  |  |  |         if (buffer) { | 
					
						
							|  |  |  |             /* Copy into the output buffer. */ | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |             STRINGLIB(fill)(&digits_end, &buffer_end, n_chars, n_zeros, | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |                  use_separator ? thousands_sep : NULL, thousands_sep_len); | 
					
						
							| 
									
										
										
										
											2009-04-03 14:45:06 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-16 20:16:10 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return count; | 
					
						
							| 
									
										
										
										
											2009-04-03 14:45:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 |