source: webkit/trunk/JavaScriptCore/jsc.cpp@ 38430

Last change on this file since 38430 was 38428, checked in by [email protected], 17 years ago

2008-11-15 Geoffrey Garen <[email protected]>

Suggested by Maciej Stachowiak.


Reverted most "opcode" => "bytecode" renames. We use "bytecode" as a
mass noun to refer to a stream of instructions. Each instruction may be
an opcode or an operand.

  • VM/CTI.cpp: (JSC::CTI::emitCTICall): (JSC::CTI::compileOpCall): (JSC::CTI::compileBinaryArithOp): (JSC::CTI::compileBinaryArithOpSlowCase): (JSC::CTI::privateCompileMainPass): (JSC::CTI::privateCompileSlowCases): (JSC::CTI::privateCompile):
  • VM/CTI.h:
  • VM/CodeBlock.cpp: (JSC::CodeBlock::printStructureIDs): (JSC::CodeBlock::dump): (JSC::CodeBlock::derefStructureIDs): (JSC::CodeBlock::refStructureIDs):
  • VM/CodeBlock.h:
  • VM/ExceptionHelpers.cpp: (JSC::createNotAnObjectError):
  • VM/Instruction.h: (JSC::Instruction::Instruction): (JSC::Instruction::):
  • VM/Machine.cpp: (JSC::BytecodeInterpreter::isOpcode): (JSC::BytecodeInterpreter::throwException): (JSC::BytecodeInterpreter::tryCachePutByID): (JSC::BytecodeInterpreter::uncachePutByID): (JSC::BytecodeInterpreter::tryCacheGetByID): (JSC::BytecodeInterpreter::uncacheGetByID): (JSC::BytecodeInterpreter::privateExecute): (JSC::BytecodeInterpreter::tryCTICachePutByID): (JSC::BytecodeInterpreter::tryCTICacheGetByID):
  • VM/Machine.h: (JSC::BytecodeInterpreter::getOpcode): (JSC::BytecodeInterpreter::getOpcodeID): (JSC::BytecodeInterpreter::isCallBytecode):
  • VM/Opcode.cpp: (JSC::): (JSC::OpcodeStats::OpcodeStats): (JSC::compareOpcodeIndices): (JSC::compareOpcodePairIndices): (JSC::OpcodeStats::~OpcodeStats): (JSC::OpcodeStats::recordInstruction): (JSC::OpcodeStats::resetLastInstruction):
  • VM/Opcode.h: (JSC::): (JSC::padOpcodeName):
  • VM/SamplingTool.cpp: (JSC::ScopeSampleRecord::sample): (JSC::SamplingTool::run): (JSC::compareOpcodeIndicesSampling): (JSC::SamplingTool::dump):
  • VM/SamplingTool.h: (JSC::ScopeSampleRecord::ScopeSampleRecord): (JSC::SamplingTool::SamplingTool):
  • bytecompiler/CodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::emitLabel): (JSC::BytecodeGenerator::emitOpcode): (JSC::BytecodeGenerator::emitJump): (JSC::BytecodeGenerator::emitJumpIfTrue): (JSC::BytecodeGenerator::emitJumpIfFalse): (JSC::BytecodeGenerator::emitMove): (JSC::BytecodeGenerator::emitUnaryOp): (JSC::BytecodeGenerator::emitPreInc): (JSC::BytecodeGenerator::emitPreDec): (JSC::BytecodeGenerator::emitPostInc): (JSC::BytecodeGenerator::emitPostDec): (JSC::BytecodeGenerator::emitBinaryOp): (JSC::BytecodeGenerator::emitEqualityOp): (JSC::BytecodeGenerator::emitUnexpectedLoad): (JSC::BytecodeGenerator::emitInstanceOf): (JSC::BytecodeGenerator::emitResolve): (JSC::BytecodeGenerator::emitGetScopedVar): (JSC::BytecodeGenerator::emitPutScopedVar): (JSC::BytecodeGenerator::emitResolveBase): (JSC::BytecodeGenerator::emitResolveWithBase): (JSC::BytecodeGenerator::emitResolveFunction): (JSC::BytecodeGenerator::emitGetById): (JSC::BytecodeGenerator::emitPutById): (JSC::BytecodeGenerator::emitPutGetter): (JSC::BytecodeGenerator::emitPutSetter): (JSC::BytecodeGenerator::emitDeleteById): (JSC::BytecodeGenerator::emitGetByVal): (JSC::BytecodeGenerator::emitPutByVal): (JSC::BytecodeGenerator::emitDeleteByVal): (JSC::BytecodeGenerator::emitPutByIndex): (JSC::BytecodeGenerator::emitNewObject): (JSC::BytecodeGenerator::emitNewArray): (JSC::BytecodeGenerator::emitNewFunction): (JSC::BytecodeGenerator::emitNewRegExp): (JSC::BytecodeGenerator::emitNewFunctionExpression): (JSC::BytecodeGenerator::emitCall): (JSC::BytecodeGenerator::emitReturn): (JSC::BytecodeGenerator::emitUnaryNoDstOp): (JSC::BytecodeGenerator::emitConstruct): (JSC::BytecodeGenerator::emitPopScope): (JSC::BytecodeGenerator::emitDebugHook): (JSC::BytecodeGenerator::emitComplexJumpScopes): (JSC::BytecodeGenerator::emitJumpScopes): (JSC::BytecodeGenerator::emitNextPropertyName): (JSC::BytecodeGenerator::emitCatch): (JSC::BytecodeGenerator::emitNewError): (JSC::BytecodeGenerator::emitJumpSubroutine): (JSC::BytecodeGenerator::emitSubroutineReturn): (JSC::BytecodeGenerator::emitPushNewScope): (JSC::BytecodeGenerator::beginSwitch):
  • bytecompiler/CodeGenerator.h:
  • jsc.cpp: (runWithScripts):
  • masm/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::emitModRm_opr): (JSC::X86Assembler::emitModRm_opr_Unchecked): (JSC::X86Assembler::emitModRm_opm): (JSC::X86Assembler::emitModRm_opm_Unchecked): (JSC::X86Assembler::emitModRm_opmsib):
  • parser/Nodes.cpp: (JSC::UnaryOpNode::emitBytecode): (JSC::BinaryOpNode::emitBytecode): (JSC::ReverseBinaryOpNode::emitBytecode): (JSC::ThrowableBinaryOpNode::emitBytecode): (JSC::emitReadModifyAssignment): (JSC::ScopeNode::ScopeNode):
  • parser/Nodes.h: (JSC::UnaryPlusNode::): (JSC::NegateNode::): (JSC::BitwiseNotNode::): (JSC::LogicalNotNode::): (JSC::MultNode::): (JSC::DivNode::): (JSC::ModNode::): (JSC::AddNode::): (JSC::SubNode::): (JSC::LeftShiftNode::): (JSC::RightShiftNode::): (JSC::UnsignedRightShiftNode::): (JSC::LessNode::): (JSC::GreaterNode::): (JSC::LessEqNode::): (JSC::GreaterEqNode::): (JSC::InstanceOfNode::): (JSC::InNode::): (JSC::EqualNode::): (JSC::NotEqualNode::): (JSC::StrictEqualNode::): (JSC::NotStrictEqualNode::): (JSC::BitAndNode::): (JSC::BitOrNode::): (JSC::BitXOrNode::):
  • runtime/StructureID.cpp: (JSC::StructureID::fromDictionaryTransition):
  • wtf/Platform.h:
  • Property svn:eol-style set to native
File size: 15.3 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "Completion.h"
26#include "CodeGenerator.h"
27#include "InitializeThreading.h"
28#include "Interpreter.h"
29#include "JSArray.h"
30#include "JSLock.h"
31#include "PrototypeFunction.h"
32#include "SamplingTool.h"
33#include <math.h>
34#include <stdio.h>
35#include <string.h>
36
37#if !PLATFORM(WIN_OS)
38#include <unistd.h>
39#endif
40
41#if HAVE(READLINE)
42#include <readline/history.h>
43#include <readline/readline.h>
44#endif
45
46#if HAVE(SYS_TIME_H)
47#include <sys/time.h>
48#endif
49
50#if PLATFORM(UNIX)
51#include <signal.h>
52#endif
53
54#if COMPILER(MSVC)
55#include <crtdbg.h>
56#include <windows.h>
57#endif
58
59#if PLATFORM(QT)
60#include <QCoreApplication>
61#include <QDateTime>
62#endif
63
64using namespace JSC;
65using namespace WTF;
66
67static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
68
69static JSValue* functionPrint(ExecState*, JSObject*, JSValue*, const ArgList&);
70static JSValue* functionDebug(ExecState*, JSObject*, JSValue*, const ArgList&);
71static JSValue* functionGC(ExecState*, JSObject*, JSValue*, const ArgList&);
72static JSValue* functionVersion(ExecState*, JSObject*, JSValue*, const ArgList&);
73static JSValue* functionRun(ExecState*, JSObject*, JSValue*, const ArgList&);
74static JSValue* functionLoad(ExecState*, JSObject*, JSValue*, const ArgList&);
75static JSValue* functionReadline(ExecState*, JSObject*, JSValue*, const ArgList&);
76static JSValue* functionQuit(ExecState*, JSObject*, JSValue*, const ArgList&);
77
78struct Options {
79 Options()
80 : interactive(false)
81 , dump(false)
82 {
83 }
84
85 bool interactive;
86 bool dump;
87 Vector<UString> fileNames;
88 Vector<UString> arguments;
89};
90
91static const char interactivePrompt[] = "> ";
92static const UString interpreterName("Interpreter");
93
94class StopWatch {
95public:
96 void start();
97 void stop();
98 long getElapsedMS(); // call stop() first
99
100private:
101#if PLATFORM(QT)
102 uint m_startTime;
103 uint m_stopTime;
104#elif PLATFORM(WIN_OS)
105 DWORD m_startTime;
106 DWORD m_stopTime;
107#else
108 // Windows does not have timeval, disabling this class for now (bug 7399)
109 timeval m_startTime;
110 timeval m_stopTime;
111#endif
112};
113
114void StopWatch::start()
115{
116#if PLATFORM(QT)
117 QDateTime t = QDateTime::currentDateTime();
118 m_startTime = t.toTime_t() * 1000 + t.time().msec();
119#elif PLATFORM(WIN_OS)
120 m_startTime = timeGetTime();
121#else
122 gettimeofday(&m_startTime, 0);
123#endif
124}
125
126void StopWatch::stop()
127{
128#if PLATFORM(QT)
129 QDateTime t = QDateTime::currentDateTime();
130 m_stopTime = t.toTime_t() * 1000 + t.time().msec();
131#elif PLATFORM(WIN_OS)
132 m_stopTime = timeGetTime();
133#else
134 gettimeofday(&m_stopTime, 0);
135#endif
136}
137
138long StopWatch::getElapsedMS()
139{
140#if PLATFORM(WIN_OS) || PLATFORM(QT)
141 return m_stopTime - m_startTime;
142#else
143 timeval elapsedTime;
144 timersub(&m_stopTime, &m_startTime, &elapsedTime);
145
146 return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f);
147#endif
148}
149
150class GlobalObject : public JSGlobalObject {
151public:
152 GlobalObject(const Vector<UString>& arguments);
153 virtual UString className() const { return "global"; }
154};
155COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
156ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
157
158GlobalObject::GlobalObject(const Vector<UString>& arguments)
159 : JSGlobalObject()
160{
161 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
162 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
163 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
164 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
165 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
166 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
167 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
168 putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
169
170 JSObject* array = constructEmptyArray(globalExec());
171 for (size_t i = 0; i < arguments.size(); ++i)
172 array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
173 putDirect(Identifier(globalExec(), "arguments"), array);
174}
175
176JSValue* functionPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
177{
178 for (unsigned i = 0; i < args.size(); ++i) {
179 if (i != 0)
180 putchar(' ');
181
182 printf("%s", args.at(exec, i)->toString(exec).UTF8String().c_str());
183 }
184
185 putchar('\n');
186 fflush(stdout);
187 return jsUndefined();
188}
189
190JSValue* functionDebug(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
191{
192 fprintf(stderr, "--> %s\n", args.at(exec, 0)->toString(exec).UTF8String().c_str());
193 return jsUndefined();
194}
195
196JSValue* functionGC(ExecState* exec, JSObject*, JSValue*, const ArgList&)
197{
198 JSLock lock(false);
199 exec->heap()->collect();
200 return jsUndefined();
201}
202
203JSValue* functionVersion(ExecState*, JSObject*, JSValue*, const ArgList&)
204{
205 // We need this function for compatibility with the Mozilla JS tests but for now
206 // we don't actually do any version-specific handling
207 return jsUndefined();
208}
209
210JSValue* functionRun(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
211{
212 StopWatch stopWatch;
213 UString fileName = args.at(exec, 0)->toString(exec);
214 Vector<char> script;
215 if (!fillBufferWithContentsOfFile(fileName, script))
216 return throwError(exec, GeneralError, "Could not open file.");
217
218 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
219
220 stopWatch.start();
221 evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
222 stopWatch.stop();
223
224 return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS());
225}
226
227JSValue* functionLoad(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
228{
229 UString fileName = args.at(exec, 0)->toString(exec);
230 Vector<char> script;
231 if (!fillBufferWithContentsOfFile(fileName, script))
232 return throwError(exec, GeneralError, "Could not open file.");
233
234 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
235 evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
236
237 return jsUndefined();
238}
239
240JSValue* functionReadline(ExecState* exec, JSObject*, JSValue*, const ArgList&)
241{
242 Vector<char, 256> line;
243 int c;
244 while ((c = getchar()) != EOF) {
245 // FIXME: Should we also break on \r?
246 if (c == '\n')
247 break;
248 line.append(c);
249 }
250 line.append('\0');
251 return jsString(exec, line.data());
252}
253
254JSValue* functionQuit(ExecState* exec, JSObject*, JSValue*, const ArgList&)
255{
256 {
257 JSLock lock(false);
258 JSGlobalData& globalData = exec->globalData();
259 globalData.heap.destroy();
260 globalData.deref();
261 }
262
263 exit(0);
264#if !COMPILER(MSVC)
265 // MSVC knows that exit(0) never returns, so it flags this return statement as unreachable.
266 return jsUndefined();
267#endif
268}
269
270// Use SEH for Release builds only to get rid of the crash report dialog
271// (luckily the same tests fail in Release and Debug builds so far). Need to
272// be in a separate main function because the jscmain function requires object
273// unwinding.
274
275#if COMPILER(MSVC) && !defined(_DEBUG)
276#define TRY __try {
277#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
278#else
279#define TRY
280#define EXCEPT(x)
281#endif
282
283int jscmain(int argc, char** argv, JSGlobalData*);
284
285int main(int argc, char** argv)
286{
287#if defined(_DEBUG) && PLATFORM(WIN_OS)
288 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
289 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
290 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
291 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
292 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
293 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
294#endif
295
296#if PLATFORM(QT)
297 QCoreApplication app(argc, argv);
298#endif
299
300 // We can't use destructors in the following code because it uses Windows
301 // Structured Exception Handling
302 int res = 0;
303 JSGlobalData* globalData = JSGlobalData::create().releaseRef();
304 TRY
305 res = jscmain(argc, argv, globalData);
306 EXCEPT(res = 3)
307
308 JSLock::lock(false);
309 globalData->heap.destroy();
310 JSLock::unlock(false);
311
312 globalData->deref();
313 return res;
314}
315
316static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool dump)
317{
318 Vector<char> script;
319
320 if (dump)
321 BytecodeGenerator::setDumpsGeneratedCode(true);
322
323#if ENABLE(OPCODE_SAMPLING)
324 BytecodeInterpreter* interpreter = globalObject->globalData()->interpreter;
325 interpreter->setSampler(new SamplingTool(machine));
326#endif
327
328 bool success = true;
329 for (size_t i = 0; i < fileNames.size(); i++) {
330 UString fileName = fileNames[i];
331
332 if (!fillBufferWithContentsOfFile(fileName, script))
333 return false; // fail early so we can catch missing files
334
335#if ENABLE(OPCODE_SAMPLING)
336 interpreter->sampler()->start();
337#endif
338 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
339 success = success && completion.complType() != Throw;
340 if (dump) {
341 if (completion.complType() == Throw)
342 printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
343 else
344 printf("End: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
345 }
346
347 globalObject->globalExec()->clearException();
348
349#if ENABLE(OPCODE_SAMPLING)
350 interpreter->sampler()->stop();
351#endif
352 }
353
354#if ENABLE(OPCODE_SAMPLING)
355 interpreter->sampler()->dump(globalObject->globalExec());
356 delete interpreter->sampler();
357#endif
358 return success;
359}
360
361static void runInteractive(GlobalObject* globalObject)
362{
363 while (true) {
364#if HAVE(READLINE)
365 char* line = readline(interactivePrompt);
366 if (!line)
367 break;
368 if (line[0])
369 add_history(line);
370 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
371 free(line);
372#else
373 puts(interactivePrompt);
374 Vector<char, 256> line;
375 int c;
376 while ((c = getchar()) != EOF) {
377 // FIXME: Should we also break on \r?
378 if (c == '\n')
379 break;
380 line.append(c);
381 }
382 line.append('\0');
383 Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
384#endif
385 if (completion.complType() == Throw)
386 printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
387 else
388 printf("%s\n", completion.value()->toString(globalObject->globalExec()).UTF8String().c_str());
389
390 globalObject->globalExec()->clearException();
391 }
392 printf("\n");
393}
394
395static void printUsageStatement()
396{
397 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
398 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
399 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
400 fprintf(stderr, " -h|--help Prints this help message\n");
401 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
402 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
403 exit(-1);
404}
405
406static void parseArguments(int argc, char** argv, Options& options)
407{
408 int i = 1;
409 for (; i < argc; ++i) {
410 const char* arg = argv[i];
411 if (strcmp(arg, "-f") == 0) {
412 if (++i == argc)
413 printUsageStatement();
414 options.fileNames.append(argv[i]);
415 continue;
416 }
417 if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
418 printUsageStatement();
419 }
420 if (strcmp(arg, "-i") == 0) {
421 options.interactive = true;
422 continue;
423 }
424 if (strcmp(arg, "-d") == 0) {
425 options.dump = true;
426 continue;
427 }
428 if (strcmp(arg, "-s") == 0) {
429#if PLATFORM(UNIX)
430 signal(SIGILL, _exit);
431 signal(SIGFPE, _exit);
432 signal(SIGBUS, _exit);
433 signal(SIGSEGV, _exit);
434#endif
435 continue;
436 }
437 if (strcmp(arg, "--") == 0) {
438 ++i;
439 break;
440 }
441 options.fileNames.append(argv[i]);
442 }
443
444 if (options.fileNames.isEmpty())
445 options.interactive = true;
446
447 for (; i < argc; ++i)
448 options.arguments.append(argv[i]);
449}
450
451int jscmain(int argc, char** argv, JSGlobalData* globalData)
452{
453 JSC::initializeThreading();
454
455 JSLock lock(false);
456
457 Options options;
458 parseArguments(argc, argv, options);
459
460 GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
461 bool success = runWithScripts(globalObject, options.fileNames, options.dump);
462 if (options.interactive && success)
463 runInteractive(globalObject);
464
465 return success ? 0 : 3;
466}
467
468static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
469{
470 FILE* f = fopen(fileName.UTF8String().c_str(), "r");
471 if (!f) {
472 fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str());
473 return false;
474 }
475
476 size_t buffer_size = 0;
477 size_t buffer_capacity = 1024;
478
479 buffer.resize(buffer_capacity);
480
481 while (!feof(f) && !ferror(f)) {
482 buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f);
483 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
484 buffer_capacity *= 2;
485 buffer.resize(buffer_capacity);
486 }
487 }
488 fclose(f);
489 buffer[buffer_size] = '\0';
490
491 return true;
492}
Note: See TracBrowser for help on using the repository browser.