cpython/Modules/_decimal/libmpdec/io.c

/*
 * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


#include "mpdecimal.h"

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "io.h"
#include "typearith.h"


/* This file contains functions for decimal <-> string conversions, including
   PEP-3101 formatting for numeric types. */


#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 7
  #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
  #pragma GCC diagnostic ignored "-Wmisleading-indentation"
  #pragma GCC diagnostic ignored "-Warray-bounds"
#endif


/*
 * Work around the behavior of tolower() and strcasecmp() in certain
 * locales. For example, in tr_TR.utf8:
 *
 * tolower((unsigned char)'I') == 'I'
 *
 * u is the exact uppercase version of l; n is strlen(l) or strlen(l)+1
 */
static inline int
_mpd_strneq(const char *s, const char *l, const char *u, size_t n)
{}

static mpd_ssize_t
strtoexp(const char *s)
{}

/*
 * Scan 'len' words. The most significant word contains 'r' digits,
 * the remaining words are full words. Skip dpoint. The string 's' must
 * consist of digits and an optional single decimal point at 'dpoint'.
 */
static void
string_to_coeff(mpd_uint_t *data, const char *s, const char *dpoint, int r,
                size_t len)
{}

/*
 * Partially verify a numeric string of the form:
 *
 *     [cdigits][.][cdigits][eE][+-][edigits]
 *
 * If successful, return a pointer to the location of the first
 * relevant coefficient digit. This digit is either non-zero or
 * part of one of the following patterns:
 *
 *     ["0\x00", "0.\x00", "0.E", "0.e", "0E", "0e"]
 *
 * The locations of a single optional dot or indicator are stored
 * in 'dpoint' and 'exp'.
 *
 * The end of the string is stored in 'end'. If an indicator [eE]
 * occurs without trailing [edigits], the condition is caught
 * later by strtoexp().
 */
static const char *
scan_dpoint_exp(const char *s, const char **dpoint, const char **exp,
                const char **end)
{}

/* scan the payload of a NaN */
static const char *
scan_payload(const char *s, const char **end)
{}

/* convert a character string to a decimal */
void
mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
                uint32_t *status)
{}

/* convert a character string to a decimal, use a maxcontext for conversion */
void
mpd_qset_string_exact(mpd_t *dec, const char *s, uint32_t *status)
{}

/* Print word x with n decimal digits to string s. dot is either NULL
   or the location of a decimal point. */
#define EXTRACT_DIGIT(s, x, d, dot)
static inline char *
word_to_string(char *s, mpd_uint_t x, int n, char *dot)
{}

/* Print exponent x to string s. Undefined for MPD_SSIZE_MIN. */
static inline char *
exp_to_string(char *s, mpd_ssize_t x)
{}

/* Print the coefficient of dec to string s. len(dec) > 0. */
static inline char *
coeff_to_string(char *s, const mpd_t *dec)
{}

/* Print the coefficient of dec to string s. len(dec) > 0. dot is either
   NULL or a pointer to the location of a decimal point. */
static inline char *
coeff_to_string_dot(char *s, char *dot, const mpd_t *dec)
{}

/* Format type */
#define MPD_FMT_LOWER
#define MPD_FMT_UPPER
#define MPD_FMT_TOSCI
#define MPD_FMT_TOENG
#define MPD_FMT_EXP
#define MPD_FMT_FIXED
#define MPD_FMT_PERCENT
#define MPD_FMT_SIGN_SPACE
#define MPD_FMT_SIGN_PLUS

/* Default place of the decimal point for MPD_FMT_TOSCI, MPD_FMT_EXP */
#define MPD_DEFAULT_DOTPLACE

/*
 * Set *result to the string representation of a decimal. Return the length
 * of *result, not including the terminating '\0' character.
 *
 * Formatting is done according to 'flags'. A return value of -1 with *result
 * set to NULL indicates MPD_Malloc_error.
 *
 * 'dplace' is the default place of the decimal point. It is always set to
 * MPD_DEFAULT_DOTPLACE except for zeros in combination with MPD_FMT_EXP.
 */
static mpd_ssize_t
_mpd_to_string(char **result, const mpd_t *dec, int flags, mpd_ssize_t dplace)
{}

char *
mpd_to_sci(const mpd_t *dec, int fmt)
{}

char *
mpd_to_eng(const mpd_t *dec, int fmt)
{}

mpd_ssize_t
mpd_to_sci_size(char **res, const mpd_t *dec, int fmt)
{}

mpd_ssize_t
mpd_to_eng_size(char **res, const mpd_t *dec, int fmt)
{}

/* Copy a single UTF-8 char to dest. See: The Unicode Standard, version 5.2,
   chapter 3.9: Well-formed UTF-8 byte sequences. */
static int
_mpd_copy_utf8(char dest[5], const char *s)
{}

int
mpd_validate_lconv(mpd_spec_t *spec)
{}

int
mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps)
{}

/*
 * The following functions assume that spec->min_width <= MPD_MAX_PREC, which
 * is made sure in mpd_qformat_spec. Then, even with a spec that inserts a
 * four-byte separator after each digit, nbytes in the following struct
 * cannot overflow.
 */

/* Multibyte string */
mpd_mbstr_t;

static inline void
_mpd_bcopy(char *dest, const char *src, mpd_ssize_t n)
{}

static inline void
_mbstr_copy_char(mpd_mbstr_t *dest, const char *src, mpd_ssize_t n)
{}

static inline void
_mbstr_copy_ascii(mpd_mbstr_t *dest, const char *src, mpd_ssize_t n)
{}

static inline void
_mbstr_copy_pad(mpd_mbstr_t *dest, mpd_ssize_t n)
{}

/*
 * Copy a numeric string to dest->data, adding separators in the integer
 * part according to spec->grouping. If leading zero padding is enabled
 * and the result is smaller than spec->min_width, continue adding zeros
 * and separators until the minimum width is reached.
 *
 * The final length of dest->data is stored in dest->nbytes. The number
 * of UTF-8 characters is stored in dest->nchars.
 *
 * First run (dest->data == NULL): determine the length of the result
 * string and store it in dest->nbytes.
 *
 * Second run (write to dest->data): data is written in chunks and in
 * reverse order, starting with the rest of the numeric string.
 */
static void
_mpd_add_sep_dot(mpd_mbstr_t *dest,
                 const char *sign, /* location of optional sign */
                 const char *src, mpd_ssize_t n_src, /* integer part and length */
                 const char *dot, /* location of optional decimal point */
                 const char *rest, mpd_ssize_t n_rest, /* remaining part and length */
                 const mpd_spec_t *spec)
{}

/*
 * Convert a numeric-string to its locale-specific appearance.
 * The string must have one of these forms:
 *
 *     1) [sign] digits [exponent-part]
 *     2) [sign] digits '.' [digits] [exponent-part]
 *
 * Not allowed, since _mpd_to_string() never returns this form:
 *
 *     3) [sign] '.' digits [exponent-part]
 *
 * Input: result->data := original numeric string (ASCII)
 *        result->bytes := strlen(result->data)
 *        result->nchars := strlen(result->data)
 *
 * Output: result->data := modified or original string
 *         result->bytes := strlen(result->data)
 *         result->nchars := number of characters (possibly UTF-8)
 */
static int
_mpd_apply_lconv(mpd_mbstr_t *result, const mpd_spec_t *spec, uint32_t *status)
{}

/* Add padding to the formatted string if necessary. */
static int
_mpd_add_pad(mpd_mbstr_t *result, const mpd_spec_t *spec, uint32_t *status)
{}

/* Round a number to prec digits. The adjusted exponent stays the same
   or increases by one if rounding up crosses a power of ten boundary.
   If result->digits would exceed MPD_MAX_PREC+1, MPD_Invalid_operation
   is set and the result is NaN. */
static inline void
_mpd_round(mpd_t *result, const mpd_t *a, mpd_ssize_t prec,
           const mpd_context_t *ctx, uint32_t *status)
{}

/*
 * Return the string representation of an mpd_t, formatted according to 'spec'.
 * The format specification is assumed to be valid. Memory errors are indicated
 * as usual. This function is quiet.
 */
char *
mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec,
                 const mpd_context_t *ctx, uint32_t *status)
{}

char *
mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx,
            uint32_t *status)
{}

/*
 * The specification has a *condition* called Invalid_operation and an
 * IEEE *signal* called Invalid_operation. The former corresponds to
 * MPD_Invalid_operation, the latter to MPD_IEEE_Invalid_operation.
 * MPD_IEEE_Invalid_operation comprises the following conditions:
 *
 * [MPD_Conversion_syntax, MPD_Division_impossible, MPD_Division_undefined,
 *  MPD_Fpu_error, MPD_Invalid_context, MPD_Invalid_operation,
 *  MPD_Malloc_error]
 *
 * In the following functions, 'flag' denotes the condition, 'signal'
 * denotes the IEEE signal.
 */

static const char *mpd_flag_string[MPD_NUM_FLAGS] =;

static const char *mpd_signal_string[MPD_NUM_FLAGS] =;

/* print conditions to buffer, separated by spaces */
int
mpd_snprint_flags(char *dest, int nmemb, uint32_t flags)
{}

/* print conditions to buffer, in list form */
int
mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[])
{}

/* print signals to buffer, in list form */
int
mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[])
{}

/* The following two functions are mainly intended for debugging. */
void
mpd_fprint(FILE *file, const mpd_t *dec)
{}

void
mpd_print(const mpd_t *dec)
{}