summaryrefslogtreecommitdiffstats
path: root/xpcom/string/nsTextFormatter.h
blob: f571043da2cef0e8ef614877ab0bb313fdaa9e10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * This code was copied from xpcom/ds/nsTextFormatter r1.3
 *           Memory model and Frozen linkage changes only.
 *                           -- Prasad <prasad@medhas.org>
 */

#ifndef nsTextFormatter_h___
#define nsTextFormatter_h___

/*
 ** API for PR printf like routines. Supports the following formats
 **	%d - decimal
 **	%u - unsigned decimal
 **	%x - unsigned hex
 **	%X - unsigned uppercase hex
 **	%o - unsigned octal
 **	%hd, %hu, %hx, %hX, %ho - 16-bit versions of above
 **	%ld, %lu, %lx, %lX, %lo - 32-bit versions of above
 **	%lld, %llu, %llx, %llX, %llo - 64 bit versions of above
 **	%s - utf8 string
 **	%S - char16_t string
 **	%c - character
 **	%p - pointer (deals with machine dependent pointer size)
 **	%f - float
 **	%g - float
 */
#include <stdio.h>
#include <stdarg.h>
#include "nscore.h"
#include "nsString.h"
#include "mozilla/Span.h"

#ifdef XPCOM_GLUE
#  error \
      "nsTextFormatter is not available in the standalone glue due to NSPR dependencies."
#endif

class nsTextFormatter {
 public:
  /*
   * sprintf into a fixed size buffer. Guarantees that the buffer is null
   * terminated. Returns the length of the written output, NOT including the
   * null terminator, or (uint32_t)-1 if an error occurs.
   */
  template <typename... T>
  static uint32_t snprintf(char16_t* aOut, uint32_t aOutLen,
                           const char16_t* aFmt, T... aArgs) {
    BoxedValue values[] = {BoxedValue(aArgs)...};
    return vsnprintf(aOut, aOutLen, aFmt,
                     mozilla::Span(values, sizeof...(aArgs)));
  }

  /*
   * sprintf into an existing nsAString, overwriting any contents it already
   * has. Infallible.
   */
  template <typename... T>
  static void ssprintf(nsAString& aOut, const char16_t* aFmt, T... aArgs) {
    BoxedValue values[] = {BoxedValue(aArgs)...};
    vssprintf(aOut, aFmt, mozilla::Span(values, sizeof...(aArgs)));
  }

 private:
  enum ArgumentKind {
    INT,
    UINT,
    POINTER,
    DOUBLE,
    STRING,
    STRING16,
    INTPOINTER,
  };

  union ValueUnion {
    int64_t mInt;
    uint64_t mUInt;
    void const* mPtr;
    double mDouble;
    char const* mString;
    char16_t const* mString16;
    int* mIntPtr;
  };

  struct BoxedValue {
    ArgumentKind mKind;
    ValueUnion mValue;

    explicit BoxedValue(int aArg) : mKind(INT) { mValue.mInt = aArg; }

    explicit BoxedValue(unsigned int aArg) : mKind(UINT) {
      mValue.mUInt = aArg;
    }

    explicit BoxedValue(long aArg) : mKind(INT) { mValue.mInt = aArg; }

    explicit BoxedValue(unsigned long aArg) : mKind(UINT) {
      mValue.mUInt = aArg;
    }

    explicit BoxedValue(long long aArg) : mKind(INT) { mValue.mInt = aArg; }

    explicit BoxedValue(unsigned long long aArg) : mKind(UINT) {
      mValue.mUInt = aArg;
    }

    explicit BoxedValue(const void* aArg) : mKind(POINTER) {
      mValue.mPtr = aArg;
    }

    explicit BoxedValue(double aArg) : mKind(DOUBLE) { mValue.mDouble = aArg; }

    explicit BoxedValue(const char* aArg) : mKind(STRING) {
      mValue.mString = aArg;
    }

    explicit BoxedValue(const char16_t* aArg) : mKind(STRING16) {
      mValue.mString16 = aArg;
    }

#if defined(MOZ_USE_CHAR16_WRAPPER)
    explicit BoxedValue(const char16ptr_t aArg) : mKind(STRING16) {
      mValue.mString16 = aArg;
    }

#endif

    explicit BoxedValue(int* aArg) : mKind(INTPOINTER) {
      mValue.mIntPtr = aArg;
    }

    bool IntCompatible() const { return mKind == INT || mKind == UINT; }

    bool PointerCompatible() const {
      return mKind == POINTER || mKind == STRING || mKind == STRING16 ||
             mKind == INTPOINTER;
    }
  };

  struct SprintfStateStr;

  static int fill2(SprintfStateStr* aState, const char16_t* aSrc, int aSrcLen,
                   int aWidth, int aFlags);
  static int fill_n(SprintfStateStr* aState, const char16_t* aSrc, int aSrcLen,
                    int aWidth, int aPrec, int aFlags);
  static int cvt_ll(SprintfStateStr* aState, uint64_t aNum, int aWidth,
                    int aPrec, int aRadix, int aFlags, const char16_t* aHexStr);
  static int cvt_f(SprintfStateStr* aState, double aDouble, int aWidth,
                   int aPrec, const char16_t aType, int aFlags);
  static int cvt_S(SprintfStateStr* aState, const char16_t* aStr, int aWidth,
                   int aPrec, int aFlags);
  static int cvt_s(SprintfStateStr* aState, const char* aStr, int aWidth,
                   int aPrec, int aFlags);
  static int dosprintf(SprintfStateStr* aState, const char16_t* aFmt,
                       mozilla::Span<BoxedValue> aValues);
  static int StringStuff(SprintfStateStr* aState, const char16_t* aStr,
                         uint32_t aLen);
  static int LimitStuff(SprintfStateStr* aState, const char16_t* aStr,
                        uint32_t aLen);
  static uint32_t vsnprintf(char16_t* aOut, uint32_t aOutLen,
                            const char16_t* aFmt,
                            mozilla::Span<BoxedValue> aValues);
  static void vssprintf(nsAString& aOut, const char16_t* aFmt,
                        mozilla::Span<BoxedValue> aValues);
};

#endif /* nsTextFormatter_h___ */