Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions
nsTextFormatter.cpp File Reference
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "prdtoa.h"
#include "prlong.h"
#include "prlog.h"
#include "prmem.h"
#include "prprf.h"
#include "nsCRT.h"
#include "nsTextFormatter.h"
#include "nsString.h"
#include "nsReadableUtils.h"

Go to the source code of this file.

Classes

struct  SprintfStateStr
struct  NumArgState

Defines

#define VARARGS_ASSIGN(foo, bar)   (foo) = (bar)
#define NAS_DEFAULT_NUM   20 /* default number of NumberedArgumentState array */
#define TYPE_INT16   0
#define TYPE_UINT16   1
#define TYPE_INTN   2
#define TYPE_UINTN   3
#define TYPE_INT32   4
#define TYPE_UINT32   5
#define TYPE_INT64   6
#define TYPE_UINT64   7
#define TYPE_STRING   8
#define TYPE_DOUBLE   9
#define TYPE_INTSTR   10
#define TYPE_UNISTRING   11
#define TYPE_UNKNOWN   20
#define _LEFT   0x1
#define _SIGNED   0x2
#define _SPACED   0x4
#define _ZEROS   0x8
#define _NEG   0x10
#define ELEMENTS_OF(array_)   (sizeof(array_) / sizeof(array_[0]))

Typedefs

typedef struct SprintfStateStr

Functions

static int fill2 (SprintfState *ss, const PRUnichar *src, int srclen, int width, int flags)
static int fill_n (SprintfState *ss, const PRUnichar *src, int srclen, int width, int prec, int type, int flags)
static int cvt_l (SprintfState *ss, long num, int width, int prec, int radix, int type, int flags, const PRUnichar *hexp)
static int cvt_ll (SprintfState *ss, PRInt64 num, int width, int prec, int radix, int type, int flags, const PRUnichar *hexp)
static int cvt_f (SprintfState *ss, double d, int width, int prec, const PRUnichar type, int flags)
static int cvt_S (SprintfState *ss, const PRUnichar *s, int width, int prec, int flags)
static int cvt_s (SprintfState *ss, const char *s, int width, int prec, int flags)
static struct NumArgStateBuildArgArray (const PRUnichar *fmt, va_list ap, int *rv, struct NumArgState *nasArray)
static int dosprintf (SprintfState *ss, const PRUnichar *fmt, va_list ap)
static int StringStuff (SprintfState *ss, const PRUnichar *sp, PRUint32 len)
static int GrowStuff (SprintfState *ss, const PRUnichar *sp, PRUint32 len)
static int LimitStuff (SprintfState *ss, const PRUnichar *sp, PRUint32 len)

Class Documentation

struct NumArgState

Definition at line 91 of file jsprf.c.

Collaboration diagram for NumArgState:
Class Members
va_list ap
int type

Define Documentation

#define _LEFT   0x1

Definition at line 112 of file nsTextFormatter.cpp.

#define _NEG   0x10

Definition at line 116 of file nsTextFormatter.cpp.

#define _SIGNED   0x2

Definition at line 113 of file nsTextFormatter.cpp.

#define _SPACED   0x4

Definition at line 114 of file nsTextFormatter.cpp.

#define _ZEROS   0x8

Definition at line 115 of file nsTextFormatter.cpp.

#define ELEMENTS_OF (   array_)    (sizeof(array_) / sizeof(array_[0]))

Definition at line 118 of file nsTextFormatter.cpp.

#define NAS_DEFAULT_NUM   20 /* default number of NumberedArgumentState array */

Definition at line 96 of file nsTextFormatter.cpp.

Definition at line 107 of file nsTextFormatter.cpp.

#define TYPE_INT16   0

Definition at line 98 of file nsTextFormatter.cpp.

#define TYPE_INT32   4

Definition at line 102 of file nsTextFormatter.cpp.

#define TYPE_INT64   6

Definition at line 104 of file nsTextFormatter.cpp.

#define TYPE_INTN   2

Definition at line 100 of file nsTextFormatter.cpp.

#define TYPE_INTSTR   10

Definition at line 108 of file nsTextFormatter.cpp.

Definition at line 106 of file nsTextFormatter.cpp.

Definition at line 99 of file nsTextFormatter.cpp.

Definition at line 103 of file nsTextFormatter.cpp.

Definition at line 105 of file nsTextFormatter.cpp.

#define TYPE_UINTN   3

Definition at line 101 of file nsTextFormatter.cpp.

Definition at line 109 of file nsTextFormatter.cpp.

#define TYPE_UNKNOWN   20

Definition at line 110 of file nsTextFormatter.cpp.

#define VARARGS_ASSIGN (   foo,
  bar 
)    (foo) = (bar)

Definition at line 73 of file nsTextFormatter.cpp.


Typedef Documentation

typedef struct SprintfStateStr

Definition at line 76 of file nsTextFormatter.cpp.


Function Documentation

static struct NumArgState* BuildArgArray ( const PRUnichar fmt,
va_list  ap,
int rv,
struct NumArgState nasArray 
) [static, read]

Definition at line 570 of file nsTextFormatter.cpp.

{
    int number = 0, cn = 0, i;
    const PRUnichar* p;
    PRUnichar  c;
    struct NumArgState* nas;

    /*
    ** first pass:
    ** detemine how many legal % I have got, then allocate space
    */
    p = fmt;
    *rv = 0;
    i = 0;
    while ((c = *p++) != 0) {
       if (c != '%') {
           continue;
        }
        /* skip %% case */
       if ((c = *p++) == '%') {
           continue;
        }

       while( c != 0 ){
           if (c > '9' || c < '0') {
                /* numbered argument csae */
              if (c == '$') {
                  if (i > 0) {
                     *rv = -1;
                     return NULL;
                  }
                  number++;
                  break;

              } else {
                    /* non-numbered argument case */
                  if (number > 0) {
                     *rv = -1;
                     return NULL;
                  }
                  i = 1;
                  break;
              }
           }
           c = *p++;
       }
    }

    if (number == 0) {
       return NULL;
    }
    
    if (number > NAS_DEFAULT_NUM) {
       nas = (struct NumArgState*)PR_MALLOC(number * sizeof(struct NumArgState));
       if (!nas) {
           *rv = -1;
           return NULL;
       }
    } else {
       nas = nasArray;
    }

    for (i = 0; i < number; i++) {
       nas[i].type = TYPE_UNKNOWN;
    }

    /*
    ** second pass:
    ** set nas[].type
    */
    p = fmt;
    while ((c = *p++) != 0) {
       if (c != '%') {
            continue;
        }
        c = *p++;
       if (c == '%') {
            continue;
        }
       cn = 0;
        /* should imporve error check later */
       while (c && c != '$') {
           cn = cn*10 + c - '0';
           c = *p++;
       }

       if (!c || cn < 1 || cn > number) {
           *rv = -1;
           break;
        }

       /* nas[cn] starts from 0, and make sure 
           nas[cn].type is not assigned */
        cn--;
       if (nas[cn].type != TYPE_UNKNOWN) {
           continue;
        }

        c = *p++;

        /* width */
        if (c == '*') {
           /* not supported feature, for the argument is not numbered */
           *rv = -1;
           break;
       } else {
           while ((c >= '0') && (c <= '9')) {
               c = *p++;
           }
       }

       /* precision */
       if (c == '.') {
           c = *p++;
           if (c == '*') {
               /* not supported feature, for the argument is not numbered */
               *rv = -1;
               break;
           } else {
               while ((c >= '0') && (c <= '9')) {
                  c = *p++;
              }
           }
       }

       /* size */
       nas[cn].type = TYPE_INTN;
       if (c == 'h') {
           nas[cn].type = TYPE_INT16;
           c = *p++;
       } else if (c == 'L') {
           /* XXX not quite sure here */
           nas[cn].type = TYPE_INT64;
           c = *p++;
       } else if (c == 'l') {
           nas[cn].type = TYPE_INT32;
           c = *p++;
           if (c == 'l') {
               nas[cn].type = TYPE_INT64;
               c = *p++;
           }
       }

       /* format */
       switch (c) {
       case 'd':
       case 'c':
       case 'i':
       case 'o':
       case 'u':
       case 'x':
       case 'X':
           break;

       case 'e':
       case 'f':
       case 'g':
           nas[cn].type = TYPE_DOUBLE;
           break;

       case 'p':
           /* XXX should use cpp */
           if (sizeof(void *) == sizeof(PRInt32)) {
              nas[cn].type = TYPE_UINT32;
           } else if (sizeof(void *) == sizeof(PRInt64)) {
               nas[cn].type = TYPE_UINT64;
           } else if (sizeof(void *) == sizeof(PRIntn)) {
               nas[cn].type = TYPE_UINTN;
           } else {
               nas[cn].type = TYPE_UNKNOWN;
           }
           break;

       case 'C':
           /* XXX not supported I suppose */
           PR_ASSERT(0);
           nas[cn].type = TYPE_UNKNOWN;
           break;

       case 'S':
           nas[cn].type = TYPE_UNISTRING;
           break;

       case 's':
           nas[cn].type = TYPE_STRING;
           break;

       case 'n':
           nas[cn].type = TYPE_INTSTR;
           break;

       default:
           PR_ASSERT(0);
           nas[cn].type = TYPE_UNKNOWN;
           break;
       }

       /* get a legal para. */
       if (nas[cn].type == TYPE_UNKNOWN) {
           *rv = -1;
           break;
       }
    }


    /*
    ** third pass
    ** fill the nas[cn].ap
    */
    if (*rv < 0) {
       if( nas != nasArray ) {
           PR_DELETE(nas);
        }
       return NULL;
    }

    cn = 0;
    while (cn < number) {
       if (nas[cn].type == TYPE_UNKNOWN) {
           cn++;
           continue;
       }

       VARARGS_ASSIGN(nas[cn].ap, ap);

       switch (nas[cn].type) {
       case TYPE_INT16:
       case TYPE_UINT16:
       case TYPE_INTN:
       case TYPE_UINTN:     (void)va_arg(ap, PRIntn);      break;

       case TYPE_INT32:     (void)va_arg(ap, PRInt32);     break;

       case TYPE_UINT32:    (void)va_arg(ap, PRUint32);    break;

       case TYPE_INT64:     (void)va_arg(ap, PRInt64);     break;

       case TYPE_UINT64:    (void)va_arg(ap, PRUint64);    break;

       case TYPE_STRING:    (void)va_arg(ap, char*);       break;

       case TYPE_INTSTR:    (void)va_arg(ap, PRIntn*);     break;

       case TYPE_DOUBLE:    (void)va_arg(ap, double);      break;

       case TYPE_UNISTRING: (void)va_arg(ap, PRUnichar*);  break;

       default:
           if( nas != nasArray ) {
              PR_DELETE( nas );
            }
           *rv = -1;
           return NULL;
       }
       cn++;
    }
    return nas;
}

Here is the caller graph for this function:

static int cvt_f ( SprintfState *  ss,
double  d,
int  width,
int  prec,
const PRUnichar  type,
int  flags 
) [static]

Definition at line 345 of file nsTextFormatter.cpp.

{
    int    mode = 2;
    int    decpt;
    int    sign;
    char   buf[256];
    char * bufp = buf;
    int    bufsz = 256;
    char   num[256];
    char * nump;
    char * endnum;
    int    numdigits = 0;
    char   exp = 'e';

    if (prec == -1) {
        prec = 6;
    } else if (prec > 50) {
        // limit precision to avoid PR_dtoa bug 108335
        // and to prevent buffers overflows
        prec = 50;
    }

    switch (type) {
    case 'f':  
        numdigits = prec;
        mode = 3;
        break;
    case 'E':
        exp = 'E';
        // no break
    case 'e':
        numdigits = prec + 1;
        mode = 2;
        break;
    case 'G':
        exp = 'E';
        // no break
    case 'g':
        if (prec == 0) {
            prec = 1;
        }
        numdigits = prec;
        mode = 2;
        break;
    default:
        NS_ERROR("invalid type passed to cvt_f");
    }
    
    if (PR_dtoa(d, mode, numdigits, &decpt, &sign, &endnum, num, bufsz) == PR_FAILURE) {
        buf[0] = '\0';
        return -1;
    }
    numdigits = endnum - num;
    nump = num;

    if (sign) {
        *bufp++ = '-';
    } else if (flags & _SIGNED) {
        *bufp++ = '+';
    }

    if (decpt == 9999) {
        while ((*bufp++ = *nump++)) { }
    } else {

        switch (type) {

        case 'E':
        case 'e':

            *bufp++ = *nump++;                
            if (prec > 0) {
                *bufp++ = '.';
                while (*nump) {
                    *bufp++ = *nump++;
                    prec--;
                }
                while (prec-- > 0) {
                    *bufp++ = '0';
                }
            }
            *bufp++ = exp;
            PR_snprintf(bufp, bufsz - (bufp - buf), "%+03d", decpt-1);
            break;

        case 'f':

            if (decpt < 1) {
                *bufp++ = '0';
                if (prec > 0) {
                    *bufp++ = '.';
                    while (decpt++ && prec-- > 0) {
                        *bufp++ = '0';
                    }
                    while (*nump && prec-- > 0) {
                        *bufp++ = *nump++;
                    }
                    while (prec-- > 0) {
                        *bufp++ = '0';
                    }
                }
            } else {
                while (*nump && decpt-- > 0) {
                    *bufp++ = *nump++;
                }
                while (decpt-- > 0) {
                    *bufp++ = '0';
                }
                if (prec > 0) {
                    *bufp++ = '.';
                    while (*nump && prec-- > 0) {
                        *bufp++ = *nump++;
                    }
                    while (prec-- > 0) {
                        *bufp++ = '0';
                    }
                }
            }
            *bufp = '\0';
            break;

        case 'G':
        case 'g':

            if ((decpt < -3) || ((decpt - 1) >= prec)) {
                *bufp++ = *nump++;
                numdigits--;
                if (numdigits > 0) {
                    *bufp++ = '.';
                    while (*nump) {
                        *bufp++ = *nump++;
                    }
                }
                *bufp++ = exp;
                PR_snprintf(bufp, bufsz - (bufp - buf), "%+03d", decpt-1);
            } else {
                if (decpt < 1) {
                    *bufp++ = '0';
                    if (prec > 0) {
                        *bufp++ = '.';
                        while (decpt++) {
                            *bufp++ = '0';
                        }
                        while (*nump) {
                            *bufp++ = *nump++;
                        }
                    }
                } else {
                    while (*nump && decpt-- > 0) {
                        *bufp++ = *nump++;
                        numdigits--;
                    }
                    while (decpt-- > 0) {
                        *bufp++ = '0';
                    }
                    if (numdigits > 0) {
                        *bufp++ = '.';
                        while (*nump) {
                            *bufp++ = *nump++;
                        }
                    }
                }
                *bufp = '\0';
            }
        }
    }

    PRUnichar rbuf[256];
    PRUnichar *rbufp = rbuf;
    bufp = buf;
    // cast to PRUnichar
    while ((*rbufp++ = *bufp++)) { }
    *rbufp = '\0';

    return fill2(ss, rbuf, nsCRT::strlen(rbuf), width, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cvt_l ( SprintfState *  ss,
long  num,
int  width,
int  prec,
int  radix,
int  type,
int  flags,
const PRUnichar hexp 
) [static]

Definition at line 259 of file nsTextFormatter.cpp.

{
    PRUnichar cvtbuf[100];
    PRUnichar *cvt;
    int digits;

    /* according to the man page this needs to happen */
    if ((prec == 0) && (num == 0)) {
       return 0;
    }

    /*
    ** Converting decimal is a little tricky. In the unsigned case we
    ** need to stop when we hit 10 digits. In the signed case, we can
    ** stop when the number is zero.
    */
    cvt = &cvtbuf[0] + ELEMENTS_OF(cvtbuf);
    digits = 0;
    while (num) {
       int digit = (((unsigned long)num) % radix) & 0xF;
       *--cvt = hexp[digit];
       digits++;
       num = (long)(((unsigned long)num) / radix);
    }
    if (digits == 0) {
       *--cvt = '0';
       digits++;
    }

    /*
    ** Now that we have the number converted without its sign, deal with
    ** the sign and zero padding.
    */
    return fill_n(ss, cvt, digits, width, prec, type, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cvt_ll ( SprintfState *  ss,
PRInt64  num,
int  width,
int  prec,
int  radix,
int  type,
int  flags,
const PRUnichar hexp 
) [static]

Definition at line 299 of file nsTextFormatter.cpp.

{
    PRUnichar cvtbuf[100];
    PRUnichar *cvt;
    int digits;
    PRInt64 rad;

    /* according to the man page this needs to happen */
    if ((prec == 0) && (LL_IS_ZERO(num))) {
       return 0;
    }

    /*
    ** Converting decimal is a little tricky. In the unsigned case we
    ** need to stop when we hit 10 digits. In the signed case, we can
    ** stop when the number is zero.
    */
    LL_I2L(rad, radix);
    cvt = &cvtbuf[0] + ELEMENTS_OF(cvtbuf);
    digits = 0;
    while (!LL_IS_ZERO(num)) {
       PRInt32 digit;
       PRInt64 quot, rem;
       LL_UDIVMOD(&quot, &rem, num, rad);
       LL_L2I(digit, rem);
       *--cvt = hexp[digit & 0xf];
       digits++;
       num = quot;
    }
    if (digits == 0) {
       *--cvt = '0';
       digits++;
    }

    /*
    ** Now that we have the number converted without its sign, deal with
    ** the sign and zero padding.
    */
    return fill_n(ss, cvt, digits, width, prec, type, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cvt_S ( SprintfState *  ss,
const PRUnichar s,
int  width,
int  prec,
int  flags 
) [static]

Definition at line 528 of file nsTextFormatter.cpp.

{
    int slen;

    if (prec == 0) {
       return 0;
    }

    /* Limit string length by precision value */
    slen = s ? nsCRT::strlen(s) : 6;
    if (prec > 0) {
       if (prec < slen) {
           slen = prec;
       }
    }

    /* and away we go */
    NS_NAMED_LITERAL_STRING(nullstr, "(null)");

    return fill2(ss, s ? s : nullstr.get(), slen, width, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cvt_s ( SprintfState *  ss,
const char *  s,
int  width,
int  prec,
int  flags 
) [static]

Definition at line 556 of file nsTextFormatter.cpp.

{
    NS_ConvertUTF8toUTF16 utf16Val(s);
    return cvt_S(ss, utf16Val.get(), width, prec, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dosprintf ( SprintfState *  ss,
const PRUnichar fmt,
va_list  ap 
) [static]

Definition at line 834 of file nsTextFormatter.cpp.

{
    PRUnichar c;
    int flags, width, prec, radix, type;
    union {
       PRUnichar ch;
       int i;
       long l;
       PRInt64 ll;
       double d;
       const char *s;
       const PRUnichar *S;
       int *ip;
    } u;
    PRUnichar space = ' ';
    const PRUnichar *fmt0;

    nsAutoString hex;
    hex.AssignLiteral("0123456789abcdef");

    nsAutoString HEX;
    HEX.AssignLiteral("0123456789ABCDEF");

    const PRUnichar *hexp;
    int rv, i;
    struct NumArgState* nas = NULL;
    struct NumArgState  nasArray[NAS_DEFAULT_NUM];
    /* in "%4$.2f" dolPt will point to . */
    const PRUnichar* dolPt = NULL;


    /*
    ** build an argument array, IF the fmt is numbered argument
    ** list style, to contain the Numbered Argument list pointers
    */
    nas = BuildArgArray (fmt, ap, &rv, nasArray);
    if (rv < 0) {
       /* the fmt contains error Numbered Argument format, jliu@netscape.com */
       PR_ASSERT(0);
       return rv;
    }

    while ((c = *fmt++) != 0) {
       if (c != '%') {
           rv = (*ss->stuff)(ss, fmt - 1, 1);
           if (rv < 0) {
              return rv;
           }
           continue;
       }
       fmt0 = fmt - 1;

       /*
       ** Gobble up the % format string. Hopefully we have handled all
       ** of the strange cases!
       */
       flags = 0;
       c = *fmt++;
       if (c == '%') {
           /* quoting a % with %% */
           rv = (*ss->stuff)(ss, fmt - 1, 1);
           if (rv < 0) {
              return rv;
           }
           continue;
       }

       if (nas != NULL) {
           /* the fmt contains the Numbered Arguments feature */
           i = 0;
           /* should imporve error check later */
           while (c && c != '$') {
              i = (i * 10) + (c - '0');
              c = *fmt++;
           }

           if (nas[i-1].type == TYPE_UNKNOWN) {
              if (nas && (nas != nasArray)) {
                  PR_DELETE(nas);
                }
              return -1;
           }

           ap = nas[i-1].ap;
           dolPt = fmt;
           c = *fmt++;
       }

       /*
        * Examine optional flags.  Note that we do not implement the
        * '#' flag of sprintf().  The ANSI C spec. of the '#' flag is
        * somewhat ambiguous and not ideal, which is perhaps why
        * the various sprintf() implementations are inconsistent
        * on this feature.
        */
       while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
           if (c == '-') flags |= _LEFT;
           if (c == '+') flags |= _SIGNED;
           if (c == ' ') flags |= _SPACED;
           if (c == '0') flags |= _ZEROS;
           c = *fmt++;
       }
       if (flags & _SIGNED) flags &= ~_SPACED;
       if (flags & _LEFT) flags &= ~_ZEROS;

       /* width */
       if (c == '*') {
           c = *fmt++;
           width = va_arg(ap, int);
       } else {
           width = 0;
           while ((c >= '0') && (c <= '9')) {
              width = (width * 10) + (c - '0');
              c = *fmt++;
           }
       }

       /* precision */
       prec = -1;
       if (c == '.') {
           c = *fmt++;
           if (c == '*') {
              c = *fmt++;
              prec = va_arg(ap, int);
           } else {
              prec = 0;
              while ((c >= '0') && (c <= '9')) {
                  prec = (prec * 10) + (c - '0');
                  c = *fmt++;
              }
           }
       }

       /* size */
       type = TYPE_INTN;
       if (c == 'h') {
           type = TYPE_INT16;
           c = *fmt++;
       } else if (c == 'L') {
           /* XXX not quite sure here */
           type = TYPE_INT64;
           c = *fmt++;
       } else if (c == 'l') {
           type = TYPE_INT32;
           c = *fmt++;
           if (c == 'l') {
              type = TYPE_INT64;
              c = *fmt++;
           }
       }

       /* format */
       hexp = hex.get();
       switch (c) {
        case 'd': 
        case 'i':                               /* decimal/integer */
           radix = 10;
           goto fetch_and_convert;

        case 'o':                               /* octal */
           radix = 8;
           type |= 1;
           goto fetch_and_convert;

        case 'u':                               /* unsigned decimal */
           radix = 10;
           type |= 1;
           goto fetch_and_convert;

        case 'x':                               /* unsigned hex */
           radix = 16;
           type |= 1;
           goto fetch_and_convert;

        case 'X':                               /* unsigned HEX */
           radix = 16;
           hexp = HEX.get();
           type |= 1;
           goto fetch_and_convert;

        fetch_and_convert:
           switch (type) {
            case TYPE_INT16:
              u.l = va_arg(ap, int);
              if (u.l < 0) {
                  u.l = -u.l;
                  flags |= _NEG;
              }
              goto do_long;
            case TYPE_UINT16:
              u.l = va_arg(ap, int) & 0xffff;
              goto do_long;
            case TYPE_INTN:
              u.l = va_arg(ap, int);
              if (u.l < 0) {
                  u.l = -u.l;
                  flags |= _NEG;
              }
              goto do_long;
            case TYPE_UINTN:
              u.l = (long)va_arg(ap, unsigned int);
              goto do_long;

            case TYPE_INT32:
              u.l = va_arg(ap, PRInt32);
              if (u.l < 0) {
                  u.l = -u.l;
                  flags |= _NEG;
              }
              goto do_long;
            case TYPE_UINT32:
              u.l = (long)va_arg(ap, PRUint32);
            do_long:
              rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);
              if (rv < 0) {
                  return rv;
              }
              break;

            case TYPE_INT64:
              u.ll = va_arg(ap, PRInt64);
              if (!LL_GE_ZERO(u.ll)) {
                  LL_NEG(u.ll, u.ll);
                  flags |= _NEG;
              }
              goto do_longlong;
            case TYPE_UINT64:
              u.ll = va_arg(ap, PRUint64);
            do_longlong:
              rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);
              if (rv < 0) {
                  return rv;
              }
              break;
           }
           break;

        case 'e':
        case 'E':
        case 'f':
        case 'g':
        case 'G':
           u.d = va_arg(ap, double);
            rv = cvt_f(ss, u.d, width, prec, c, flags);
           if (rv < 0) {
              return rv;
           }
           break;

        case 'c':
           u.ch = va_arg(ap, int);
            if ((flags & _LEFT) == 0) {
                while (width-- > 1) {
                    rv = (*ss->stuff)(ss, &space, 1);
                    if (rv < 0) {
                        return rv;
                    }
                }
            }
           rv = (*ss->stuff)(ss, &u.ch, 1);
           if (rv < 0) {
              return rv;
           }
            if (flags & _LEFT) {
                while (width-- > 1) {
                    rv = (*ss->stuff)(ss, &space, 1);
                    if (rv < 0) {
                        return rv;
                    }
                }
            }
           break;

        case 'p':
           if (sizeof(void *) == sizeof(PRInt32)) {
              type = TYPE_UINT32;
           } else if (sizeof(void *) == sizeof(PRInt64)) {
              type = TYPE_UINT64;
           } else if (sizeof(void *) == sizeof(int)) {
              type = TYPE_UINTN;
           } else {
              PR_ASSERT(0);
              break;
           }
           radix = 16;
           goto fetch_and_convert;

#if 0
        case 'C':
           /* XXX not supported I suppose */
           PR_ASSERT(0);
           break;
#endif

        case 'S':
           u.S = va_arg(ap, const PRUnichar*);
           rv = cvt_S(ss, u.S, width, prec, flags);
           if (rv < 0) {
              return rv;
           }
           break;

        case 's':
           u.s = va_arg(ap, const char*);
           rv = cvt_s(ss, u.s, width, prec, flags);
           if (rv < 0) {
              return rv;
           }
           break;

        case 'n':
           u.ip = va_arg(ap, int*);
           if (u.ip) {
              *u.ip = ss->cur - ss->base;
           }
           break;

        default:
           /* Not a % token after all... skip it */
#if 0
           PR_ASSERT(0);
#endif
            PRUnichar perct = '%'; 
           rv = (*ss->stuff)(ss, &perct, 1);
           if (rv < 0) {
              return rv;
           }
           rv = (*ss->stuff)(ss, fmt - 1, 1);
           if (rv < 0) {
              return rv;
           }
       }
    }

    /* Stuff trailing NUL */
    PRUnichar null = '\0';

    rv = (*ss->stuff)(ss, &null, 1);

    if( nas && ( nas != nasArray ) ){
       PR_DELETE( nas );
    }

    return rv;
}

Here is the call graph for this function:

static int fill2 ( SprintfState *  ss,
const PRUnichar src,
int  srclen,
int  width,
int  flags 
) [static]

Definition at line 123 of file nsTextFormatter.cpp.

{
    PRUnichar space = ' ';
    int rv;
    
    width -= srclen;
    /* Right adjusting */
    if ((width > 0) && ((flags & _LEFT) == 0)) {
       if (flags & _ZEROS) {
           space = '0';
       }
       while (--width >= 0) {
           rv = (*ss->stuff)(ss, &space, 1);
           if (rv < 0) {
              return rv;
           }
       }
    }

    /* Copy out the source data */
    rv = (*ss->stuff)(ss, src, srclen);
    if (rv < 0) {
       return rv;
    }
    
    /* Left adjusting */
    if ((width > 0) && ((flags & _LEFT) != 0)) {
       while (--width >= 0) {
           rv = (*ss->stuff)(ss, &space, 1);
           if (rv < 0) {
              return rv;
           }
       }
    }
    return 0;
}

Here is the caller graph for this function:

static int fill_n ( SprintfState *  ss,
const PRUnichar src,
int  srclen,
int  width,
int  prec,
int  type,
int  flags 
) [static]

Definition at line 164 of file nsTextFormatter.cpp.

{
    int zerowidth   = 0;
    int precwidth   = 0;
    int signwidth   = 0;
    int leftspaces  = 0;
    int rightspaces = 0;
    int cvtwidth;
    int rv;
    PRUnichar sign;
    PRUnichar space = ' ';
    PRUnichar zero = '0';

    if ((type & 1) == 0) {
       if (flags & _NEG) {
           sign = '-';
           signwidth = 1;
       } else if (flags & _SIGNED) {
           sign = '+';
           signwidth = 1;
       } else if (flags & _SPACED) {
           sign = ' ';
           signwidth = 1;
       }
    }
    cvtwidth = signwidth + srclen;

    if (prec > 0) {
       if (prec > srclen) {
            /* Need zero filling */
           precwidth = prec - srclen;
           cvtwidth += precwidth;
       }
    }

    if ((flags & _ZEROS) && (prec < 0)) {
       if (width > cvtwidth) {
            /* Zero filling */
           zerowidth = width - cvtwidth;
           cvtwidth += zerowidth;
       }
    }

    if (flags & _LEFT) {
       if (width > cvtwidth) {
           /* Space filling on the right (i.e. left adjusting) */
           rightspaces = width - cvtwidth;
       }
    } else {
       if (width > cvtwidth) {
           /* Space filling on the left (i.e. right adjusting) */
           leftspaces = width - cvtwidth;
       }
    }
    while (--leftspaces >= 0) {
       rv = (*ss->stuff)(ss, &space, 1);
       if (rv < 0) {
           return rv;
       }
    }
    if (signwidth) {
       rv = (*ss->stuff)(ss, &sign, 1);
       if (rv < 0) {
           return rv;
       }
    }
    while (--precwidth >= 0) {
       rv = (*ss->stuff)(ss,  &space, 1);
       if (rv < 0) {
           return rv;
       }
    }
    while (--zerowidth >= 0) {
       rv = (*ss->stuff)(ss,  &zero, 1);
       if (rv < 0) {
           return rv;
       }
    }
    rv = (*ss->stuff)(ss, src, srclen);
    if (rv < 0) {
       return rv;
    }
    while (--rightspaces >= 0) {
       rv = (*ss->stuff)(ss,  &space, 1);
       if (rv < 0) {
           return rv;
       }
    }
    return 0;
}

Here is the caller graph for this function:

static int GrowStuff ( SprintfState *  ss,
const PRUnichar sp,
PRUint32  len 
) [static]

Definition at line 1203 of file nsTextFormatter.cpp.

{
    ptrdiff_t off;
    PRUnichar *newbase;
    PRUint32 newlen;

    off = ss->cur - ss->base;
    if (off + len >= ss->maxlen) {
       /* Grow the buffer */
       newlen = ss->maxlen + ((len > 32) ? len : 32);
       if (ss->base) {
           newbase = (PRUnichar*) PR_REALLOC(ss->base, newlen*sizeof(PRUnichar));
       } else {
           newbase = (PRUnichar*) PR_MALLOC(newlen*sizeof(PRUnichar));
       }
       if (!newbase) {
           /* Ran out of memory */
           return -1;
       }
       ss->base = newbase;
       ss->maxlen = newlen;
       ss->cur = ss->base + off;
    }

    /* Copy data */
    while (len) {
       --len;
       *ss->cur++ = *sp++;
    }
    PR_ASSERT((PRUint32)(ss->cur - ss->base) <= ss->maxlen);
    return 0;
}
static int LimitStuff ( SprintfState *  ss,
const PRUnichar sp,
PRUint32  len 
) [static]

Definition at line 1305 of file nsTextFormatter.cpp.

{
    PRUint32 limit = ss->maxlen - (ss->cur - ss->base);

    if (len > limit) {
       len = limit;
    }
    while (len) {
       --len;
       *ss->cur++ = *sp++;
    }
    return 0;
}
static int StringStuff ( SprintfState *  ss,
const PRUnichar sp,
PRUint32  len 
) [static]

Definition at line 1183 of file nsTextFormatter.cpp.

{
    ptrdiff_t off = ss->cur - ss->base;
    
    nsAString* str = NS_STATIC_CAST(nsAString*,ss->stuffclosure);
    str->Append(sp, len);

    // we can assume contiguous storage
    nsAString::iterator begin;
    str->BeginWriting(begin);
    ss->base = begin.get();
    ss->cur = ss->base + off;

    return 0;
}