@@ -46,6 +46,11 @@ THREAD_ST WORD Output::s_color = 0;
46
46
THREAD_ST bool Output::s_hasColor = false ;
47
47
THREAD_ST bool Output::s_capture = false ;
48
48
49
+ THREAD_ST bool Output::hasDoneAlignPrefixForThisLine = false ;
50
+ THREAD_ST bool Output::usingCustomAlignAndPrefix = false ;
51
+ THREAD_ST size_t Output::align = 0 ;
52
+ THREAD_ST const char16* Output::prefix = nullptr ;
53
+
49
54
#define MAX_OUTPUT_BUFFER_SIZE 10 * 1024 * 1024 // 10 MB maximum before we force a flush
50
55
51
56
size_t __cdecl
@@ -282,6 +287,86 @@ Output::VPrint(const char16 *form, va_list argptr)
282
287
size_t __cdecl
283
288
Output::PrintBuffer (const char16 * buf, size_t size)
284
289
{
290
+ // Handle custom line prefixing
291
+ bool internallyAllocatedBuffer = false ;
292
+ if (usingCustomAlignAndPrefix)
293
+ {
294
+ if (hasDoneAlignPrefixForThisLine && wcschr (buf, ' \n ' ) == nullptr )
295
+ {
296
+ // no newlines, and we've already prefixed this line, so nothing to do
297
+ }
298
+ else
299
+ {
300
+ size_t newbufsize = size + align;
301
+ char16* newbuf = (char16*)calloc (newbufsize, sizeof (char16));
302
+ AssertOrFailFastMsg (newbuf != nullptr , " Ran out of memory while printing output" );
303
+ internallyAllocatedBuffer = true ;
304
+ const char16* currentReadIndex = buf;
305
+ char16* currentWriteIndex = newbuf;
306
+ auto ensureSpace = [¤tWriteIndex, &newbuf, &newbufsize](size_t numCharsWantToWrite)
307
+ {
308
+ size_t charsWritten = (currentWriteIndex - newbuf); // pointer subtraction is number of elements of pointed type between pointers
309
+ size_t remaining = newbufsize - charsWritten;
310
+ if (numCharsWantToWrite + 1 > remaining)
311
+ {
312
+ char16* tempbuf = (char16*)realloc (newbuf, newbufsize * sizeof (char16) * 2 );
313
+ AssertOrFailFastMsg (tempbuf != nullptr , " Ran out of memory while printing output" );
314
+ newbuf = tempbuf;
315
+ newbufsize = newbufsize * 2 ;
316
+ currentWriteIndex = newbuf + charsWritten;
317
+ }
318
+ };
319
+ const size_t prefixlength = wcslen (prefix);
320
+ size_t oldS_Column = Output::s_Column;
321
+ while (currentReadIndex < buf + size)
322
+ {
323
+ if (!hasDoneAlignPrefixForThisLine)
324
+ {
325
+ // attempt to write the alignment
326
+ {
327
+ unsigned int alignspacesneeded = 1 ; // always put at least one space
328
+ if (oldS_Column < align)
329
+ {
330
+ alignspacesneeded = (unsigned int )(align - oldS_Column);
331
+ }
332
+ ensureSpace (alignspacesneeded);
333
+ for (unsigned int i = 0 ; i < alignspacesneeded; i++)
334
+ {
335
+ *(currentWriteIndex++) = ' ' ;
336
+ }
337
+ }
338
+ // attempt to write the prefix
339
+ ensureSpace (prefixlength);
340
+ js_wmemcpy_s (currentWriteIndex, (newbuf + newbufsize) - currentWriteIndex, Output::prefix, prefixlength);
341
+ currentWriteIndex += prefixlength;
342
+ oldS_Column = align + prefixlength;
343
+ hasDoneAlignPrefixForThisLine = true ;
344
+ }
345
+ const char16* endOfLine = wcschr (currentReadIndex, ' \n ' );
346
+ size_t charsToCopy = 0 ;
347
+ if (endOfLine != nullptr )
348
+ {
349
+ charsToCopy = (endOfLine - currentReadIndex) + 1 ; // We want to grab the newline character as part of this line
350
+ oldS_Column = 0 ; // We're ending this line, and want the next to be calculated properly
351
+ hasDoneAlignPrefixForThisLine = false ; // The next line will need this
352
+ }
353
+ else
354
+ {
355
+ charsToCopy = (buf + size) - currentReadIndex; // the rest of the input buffer
356
+ oldS_Column += charsToCopy; // Will be reset anyway later on
357
+ }
358
+ ensureSpace (endOfLine - currentReadIndex);
359
+ js_wmemcpy_s (currentWriteIndex, (newbuf + newbufsize) - currentWriteIndex, currentReadIndex, charsToCopy);
360
+ currentReadIndex += charsToCopy;
361
+ currentWriteIndex += charsToCopy;
362
+ }
363
+ // null terminate becuase there's no real reason not to
364
+ ensureSpace (1 );
365
+ *(currentWriteIndex++) = ' \0 ' ;
366
+ buf = newbuf;
367
+ size = (currentWriteIndex - newbuf) - 1 ; // not counting the terminator here though, to align with vsnwprintf_s's behavior
368
+ }
369
+ }
285
370
Output::s_Column += size;
286
371
const char16 * endbuf = wcschr (buf, ' \n ' );
287
372
while (endbuf != nullptr )
@@ -443,15 +528,27 @@ void Output::DirectPrint(char16 const * string)
443
528
void
444
529
Output::SkipToColumn (size_t column)
445
530
{
446
- if (column <= Output::s_Column)
531
+ size_t columnbias = 0 ;
532
+ // If we're using a custom alignment and prefix, we want to do this relative to that
533
+ if (usingCustomAlignAndPrefix)
534
+ {
535
+ // If we've already added the alignment and prefix, we need to add the alignment to our column number here
536
+ columnbias = align + wcslen (prefix);
537
+ }
538
+ size_t reference = 0 ;
539
+ if (Output::s_Column > columnbias)
540
+ {
541
+ reference = Output::s_Column - columnbias;
542
+ }
543
+ if (column <= reference)
447
544
{
448
545
Output::Print (_u (" " ));
449
546
return ;
450
547
}
451
548
452
549
// compute distance to our destination
453
550
454
- size_t dist = column - Output::s_Column ;
551
+ size_t dist = column - reference ;
455
552
456
553
// Print at least one space
457
554
while (dist > 0 )
@@ -564,3 +661,20 @@ Output::CaptureEnd()
564
661
565
662
return returnBuffer;
566
663
}
664
+
665
+ void
666
+ Output::SetAlignAndPrefix (unsigned int align, const char16 *prefix)
667
+ {
668
+ Output::hasDoneAlignPrefixForThisLine = false ;
669
+ Output::usingCustomAlignAndPrefix = true ;
670
+ Output::prefix = prefix;
671
+ Output::align = align;
672
+ }
673
+ void
674
+ Output::ResetAlignAndPrefix ()
675
+ {
676
+ Output::hasDoneAlignPrefixForThisLine = false ;
677
+ Output::usingCustomAlignAndPrefix = false ;
678
+ Output::prefix = nullptr ;
679
+ Output::align = 0 ;
680
+ }
0 commit comments