1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_V8UTILS_H_
29#define V8_V8UTILS_H_
30
31#include "utils.h"
32#include "platform.h"  // For va_list on Solaris.
33
34namespace v8 {
35namespace internal {
36
37// ----------------------------------------------------------------------------
38// I/O support.
39
40#if __GNUC__ >= 4
41// On gcc we can ask the compiler to check the types of %d-style format
42// specifiers and their associated arguments.  TODO(erikcorry) fix this
43// so it works on MacOSX.
44#if defined(__MACH__) && defined(__APPLE__)
45#define PRINTF_CHECKING
46#define FPRINTF_CHECKING
47#else  // MacOsX.
48#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
49#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
50#endif
51#else
52#define PRINTF_CHECKING
53#define FPRINTF_CHECKING
54#endif
55
56// Our version of printf().
57void PRINTF_CHECKING PrintF(const char* format, ...);
58void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
59
60// Our version of fflush.
61void Flush(FILE* out);
62
63inline void Flush() {
64  Flush(stdout);
65}
66
67
68// Read a line of characters after printing the prompt to stdout. The resulting
69// char* needs to be disposed off with DeleteArray by the caller.
70char* ReadLine(const char* prompt);
71
72
73// Read and return the raw bytes in a file. the size of the buffer is returned
74// in size.
75// The returned buffer must be freed by the caller.
76byte* ReadBytes(const char* filename, int* size, bool verbose = true);
77
78
79// Append size chars from str to the file given by filename.
80// The file is overwritten. Returns the number of chars written.
81int AppendChars(const char* filename,
82                const char* str,
83                int size,
84                bool verbose = true);
85
86
87// Write size chars from str to the file given by filename.
88// The file is overwritten. Returns the number of chars written.
89int WriteChars(const char* filename,
90               const char* str,
91               int size,
92               bool verbose = true);
93
94
95// Write size bytes to the file given by filename.
96// The file is overwritten. Returns the number of bytes written.
97int WriteBytes(const char* filename,
98               const byte* bytes,
99               int size,
100               bool verbose = true);
101
102
103// Write the C code
104// const char* <varname> = "<str>";
105// const int <varname>_len = <len>;
106// to the file given by filename. Only the first len chars are written.
107int WriteAsCFile(const char* filename, const char* varname,
108                 const char* str, int size, bool verbose = true);
109
110
111// Data structures
112
113template <typename T>
114inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
115                                             int length) {
116  return Vector< Handle<Object> >(
117      reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
118}
119
120// Memory
121
122// Copies data from |src| to |dst|.  The data spans MUST not overlap.
123template <typename T>
124inline void CopyWords(T* dst, T* src, int num_words) {
125  STATIC_ASSERT(sizeof(T) == kPointerSize);
126  ASSERT(Min(dst, src) + num_words <= Max(dst, src));
127  ASSERT(num_words > 0);
128
129  // Use block copying memcpy if the segment we're copying is
130  // enough to justify the extra call/setup overhead.
131  static const int kBlockCopyLimit = 16;
132
133  if (num_words >= kBlockCopyLimit) {
134    memcpy(dst, src, num_words * kPointerSize);
135  } else {
136    int remaining = num_words;
137    do {
138      remaining--;
139      *dst++ = *src++;
140    } while (remaining > 0);
141  }
142}
143
144
145template <typename T, typename U>
146inline void MemsetPointer(T** dest, U* value, int counter) {
147#ifdef DEBUG
148  T* a = NULL;
149  U* b = NULL;
150  a = b;  // Fake assignment to check assignability.
151  USE(a);
152#endif  // DEBUG
153#if defined(V8_HOST_ARCH_IA32)
154#define STOS "stosl"
155#elif defined(V8_HOST_ARCH_X64)
156#define STOS "stosq"
157#endif
158
159#if defined(__GNUC__) && defined(STOS)
160  asm volatile(
161      "cld;"
162      "rep ; " STOS
163      : "+&c" (counter), "+&D" (dest)
164      : "a" (value)
165      : "memory", "cc");
166#else
167  for (int i = 0; i < counter; i++) {
168    dest[i] = value;
169  }
170#endif
171
172#undef STOS
173}
174
175
176// Simple wrapper that allows an ExternalString to refer to a
177// Vector<const char>. Doesn't assume ownership of the data.
178class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
179 public:
180  explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
181
182  virtual const char* data() const { return data_.start(); }
183
184  virtual size_t length() const { return data_.length(); }
185
186 private:
187  Vector<const char> data_;
188};
189
190
191// Simple support to read a file into a 0-terminated C-string.
192// The returned buffer must be freed by the caller.
193// On return, *exits tells whether the file existed.
194Vector<const char> ReadFile(const char* filename,
195                            bool* exists,
196                            bool verbose = true);
197Vector<const char> ReadFile(FILE* file,
198                            bool* exists,
199                            bool verbose = true);
200
201
202
203// Copy from ASCII/16bit chars to ASCII/16bit chars.
204template <typename sourcechar, typename sinkchar>
205inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
206  sinkchar* limit = dest + chars;
207#ifdef V8_HOST_CAN_READ_UNALIGNED
208  if (sizeof(*dest) == sizeof(*src)) {
209    if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) {
210      OS::MemCopy(dest, src, chars * sizeof(*dest));
211      return;
212    }
213    // Number of characters in a uintptr_t.
214    static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest);  // NOLINT
215    while (dest <= limit - kStepSize) {
216      *reinterpret_cast<uintptr_t*>(dest) =
217          *reinterpret_cast<const uintptr_t*>(src);
218      dest += kStepSize;
219      src += kStepSize;
220    }
221  }
222#endif
223  while (dest < limit) {
224    *dest++ = static_cast<sinkchar>(*src++);
225  }
226}
227
228
229// A resource for using mmapped files to back external strings that are read
230// from files.
231class MemoryMappedExternalResource: public
232    v8::String::ExternalAsciiStringResource {
233 public:
234  explicit MemoryMappedExternalResource(const char* filename);
235  MemoryMappedExternalResource(const char* filename,
236                               bool remove_file_on_cleanup);
237  virtual ~MemoryMappedExternalResource();
238
239  virtual const char* data() const { return data_; }
240  virtual size_t length() const { return length_; }
241
242  bool exists() const { return file_ != NULL; }
243  bool is_empty() const { return length_ == 0; }
244
245  bool EnsureIsAscii(bool abort_if_failed) const;
246  bool EnsureIsAscii() const { return EnsureIsAscii(true); }
247  bool IsAscii() const { return EnsureIsAscii(false); }
248
249 private:
250  void Init(const char* filename);
251
252  char* filename_;
253  OS::MemoryMappedFile* file_;
254
255  const char* data_;
256  size_t length_;
257  bool remove_file_on_cleanup_;
258};
259
260class StringBuilder : public SimpleStringBuilder {
261 public:
262  explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
263  StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
264
265  // Add formatted contents to the builder just like printf().
266  void AddFormatted(const char* format, ...);
267
268  // Add formatted contents like printf based on a va_list.
269  void AddFormattedList(const char* format, va_list list);
270 private:
271  DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
272};
273
274} }  // namespace v8::internal
275
276#endif  // V8_V8UTILS_H_
277