koffi 2.7.0 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1932,6 +1932,23 @@ bool GetDebugFlag(const char *name)
1932
1932
  }
1933
1933
  }
1934
1934
 
1935
+ #ifndef NDEBUG
1936
+ const char *DebugLogContext(const char *filename, int line)
1937
+ {
1938
+ static RG_THREAD_LOCAL LocalArray<char, 1024> buf;
1939
+
1940
+ buf.len = Fmt(buf.data, " [%1:%2] ", filename, line).len;
1941
+
1942
+ if (buf.len > 32) {
1943
+ char *ptr = buf.end() - 32;
1944
+ memcpy(ptr, " [...", 6);
1945
+ return ptr;
1946
+ } else {
1947
+ return buf.data;
1948
+ }
1949
+ }
1950
+ #endif
1951
+
1935
1952
  static void RunLogFilter(Size idx, LogLevel level, const char *ctx, const char *msg)
1936
1953
  {
1937
1954
  const std::function<LogFilterFunc> &func = *log_filters[idx];
@@ -2001,9 +2018,9 @@ void DefaultLogHandler(LogLevel level, const char *ctx, const char *msg)
2001
2018
  {
2002
2019
  switch (level) {
2003
2020
  case LogLevel::Debug:
2004
- case LogLevel::Info: { PrintLn(stderr, "%!D..%1%2%!0%3", ctx ? ctx : "", ctx ? ": " : "", msg); } break;
2005
- case LogLevel::Warning: { PrintLn(stderr, "%!M..%1%2%!0%3", ctx ? ctx : "", ctx ? ": " : "", msg); } break;
2006
- case LogLevel::Error: { PrintLn(stderr, "%!R..%1%2%!0%3", ctx ? ctx : "", ctx ? ": " : "", msg); } break;
2021
+ case LogLevel::Info: { PrintLn(stderr, "%!D..%1%!0%2", ctx ? ctx : "", msg); } break;
2022
+ case LogLevel::Warning: { PrintLn(stderr, "%!M..%1%!0%2", ctx ? ctx : "", msg); } break;
2023
+ case LogLevel::Error: { PrintLn(stderr, "%!R..%1%!0%2", ctx ? ctx : "", msg); } break;
2007
2024
  }
2008
2025
 
2009
2026
  fflush(stderr);
@@ -2047,11 +2064,10 @@ bool RedirectLogToWindowsEvents(const char *name)
2047
2064
 
2048
2065
  // Append context
2049
2066
  if (ctx) {
2050
- Size len = ConvertUtf8ToWin32Wide(ctx, buf_w.Take(0, RG_LEN(buf_w.data) / 2));
2067
+ Size len = ConvertUtf8ToWin32Wide(ctx, buf_w.TakeAvailable());
2051
2068
  if (len < 0)
2052
2069
  return;
2053
- wcscpy(buf_w.data + len, L": ");
2054
- buf_w.len += len + 2;
2070
+ buf_w.len += len;
2055
2071
  }
2056
2072
 
2057
2073
  // Append message
@@ -3881,8 +3897,11 @@ bool CreateOverlappedPipe(bool overlap0, bool overlap1, PipeMode mode, HANDLE ou
3881
3897
 
3882
3898
  void CloseHandleSafe(HANDLE *handle_ptr)
3883
3899
  {
3884
- if (*handle_ptr && *handle_ptr != INVALID_HANDLE_VALUE) {
3885
- CloseHandle(*handle_ptr);
3900
+ HANDLE h = *handle_ptr;
3901
+
3902
+ if (h && h != INVALID_HANDLE_VALUE) {
3903
+ CancelIo(h);
3904
+ CloseHandle(h);
3886
3905
  }
3887
3906
 
3888
3907
  *handle_ptr = nullptr;
@@ -4021,6 +4040,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
4021
4040
  CloseHandleSafe(&si.hStdOutput);
4022
4041
  CloseHandleSafe(&si.hStdError);
4023
4042
  };
4043
+
4024
4044
  if (in_func.IsValid() || out_func.IsValid()) {
4025
4045
  if (!DuplicateHandle(GetCurrentProcess(), in_func.IsValid() ? in_pipe[0] : GetStdHandle(STD_INPUT_HANDLE),
4026
4046
  GetCurrentProcess(), &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
@@ -4095,6 +4115,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
4095
4115
  if (proc_in.err && proc_in.err != ERROR_BROKEN_PIPE && proc_in.err != ERROR_NO_DATA) {
4096
4116
  LogError("Failed to write to process: %1", GetWin32ErrorString(proc_in.err));
4097
4117
  }
4118
+
4098
4119
  proc_in.pending = true;
4099
4120
  }
4100
4121
 
@@ -4111,30 +4132,23 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
4111
4132
  }
4112
4133
  }
4113
4134
 
4114
- if (proc_out.err && proc_out.err != ERROR_BROKEN_PIPE && proc_out.err != ERROR_NO_DATA) {
4115
- LogError("Failed to read process output: %1", GetWin32ErrorString(proc_out.err));
4135
+ if (proc_out.err) {
4136
+ if (proc_out.err != ERROR_BROKEN_PIPE && proc_out.err != ERROR_NO_DATA) {
4137
+ LogError("Failed to read process output: %1", GetWin32ErrorString(proc_out.err));
4138
+ }
4139
+ break;
4116
4140
  }
4141
+
4117
4142
  proc_out.pending = true;
4118
4143
  }
4119
4144
 
4120
- HANDLE events[2] = {
4121
- process_handle,
4122
- console_ctrl_event
4123
- };
4124
-
4125
- running = (WaitForMultipleObjectsEx(RG_LEN(events), events, FALSE, INFINITE, TRUE) > WAIT_OBJECT_0 + 1);
4145
+ running = (WaitForSingleObjectEx(console_ctrl_event, INFINITE, TRUE) != WAIT_OBJECT_0);
4126
4146
  }
4127
4147
  }
4128
4148
 
4129
4149
  // Terminate any remaining I/O
4130
- if (in_pipe[1]) {
4131
- CancelIo(in_pipe[1]);
4132
- CloseHandleSafe(&in_pipe[1]);
4133
- }
4134
- if (out_pipe[0]) {
4135
- CancelIo(out_pipe[0]);
4136
- CloseHandleSafe(&out_pipe[0]);
4137
- }
4150
+ CloseHandleSafe(&in_pipe[1]);
4151
+ CloseHandleSafe(&out_pipe[0]);
4138
4152
 
4139
4153
  // Wait for process exit
4140
4154
  {
@@ -6184,6 +6198,15 @@ StreamWriter stderr_st(stderr, "<stderr>");
6184
6198
  static CreateDecompressorFunc *DecompressorFunctions[RG_LEN(CompressionTypeNames)];
6185
6199
  static CreateCompressorFunc *CompressorFunctions[RG_LEN(CompressionTypeNames)];
6186
6200
 
6201
+ void StreamReader::SetDecoder(StreamDecoder *decoder)
6202
+ {
6203
+ RG_ASSERT(decoder);
6204
+ RG_ASSERT(!filename);
6205
+ RG_ASSERT(!this->decoder);
6206
+
6207
+ this->decoder = decoder;
6208
+ }
6209
+
6187
6210
  bool StreamReader::Open(Span<const uint8_t> buf, const char *filename,
6188
6211
  CompressionType compression_type)
6189
6212
  {
@@ -6288,9 +6311,9 @@ bool StreamReader::Close(bool implicit)
6288
6311
  {
6289
6312
  RG_ASSERT(implicit || this != &stdin_st);
6290
6313
 
6291
- if (decompressor) {
6292
- RG_ASSERT(compression_type != CompressionType::None);
6293
- delete decompressor;
6314
+ if (decoder) {
6315
+ delete decoder;
6316
+ decoder = nullptr;
6294
6317
  }
6295
6318
 
6296
6319
  switch (source.type) {
@@ -6310,7 +6333,6 @@ bool StreamReader::Close(bool implicit)
6310
6333
 
6311
6334
  filename = nullptr;
6312
6335
  error = true;
6313
- compression_type = CompressionType::None;
6314
6336
  source.type = SourceType::Memory;
6315
6337
  source.eof = false;
6316
6338
  eof = false;
@@ -6325,6 +6347,11 @@ bool StreamReader::Rewind()
6325
6347
  if (error) [[unlikely]]
6326
6348
  return false;
6327
6349
 
6350
+ if (decoder) [[unlikely]] {
6351
+ LogError("Cannot rewind stream with decoder");
6352
+ return false;
6353
+ }
6354
+
6328
6355
  switch (source.type) {
6329
6356
  case SourceType::Memory: { source.u.memory.pos = 0; } break;
6330
6357
  case SourceType::File: {
@@ -6341,14 +6368,6 @@ bool StreamReader::Rewind()
6341
6368
  } break;
6342
6369
  }
6343
6370
 
6344
- if (decompressor) {
6345
- RG_ASSERT(compression_type != CompressionType::None);
6346
- delete decompressor;
6347
-
6348
- if (!InitDecompressor(compression_type))
6349
- return false;
6350
- }
6351
-
6352
6371
  source.eof = false;
6353
6372
  eof = false;
6354
6373
 
@@ -6378,14 +6397,10 @@ Size StreamReader::Read(Span<uint8_t> out_buf)
6378
6397
  return -1;
6379
6398
 
6380
6399
  Size read_len = 0;
6381
- if (decompressor) {
6382
- RG_ASSERT(compression_type != CompressionType::None);
6383
-
6384
- read_len = decompressor->Read(out_buf.len, out_buf.ptr);
6400
+ if (decoder) {
6401
+ read_len = decoder->Read(out_buf.len, out_buf.ptr);
6385
6402
  error |= (read_len < 0);
6386
6403
  } else {
6387
- RG_ASSERT(compression_type == CompressionType::None);
6388
-
6389
6404
  read_len = ReadRaw(out_buf.len, out_buf.ptr);
6390
6405
  eof = source.eof;
6391
6406
  }
@@ -6423,7 +6438,7 @@ Size StreamReader::ReadAll(Size max_len, HeapArray<uint8_t> *out_buf)
6423
6438
  // For some files (such as in /proc), the file size is reported as 0 even though there
6424
6439
  // is content inside, because these files are generated on demand. So we need to take
6425
6440
  // the slow path for apparently empty files.
6426
- if (compression_type == CompressionType::None && ComputeRawLen() > 0) {
6441
+ if (!decoder && ComputeRawLen() > 0) {
6427
6442
  if (raw_len > max_len) {
6428
6443
  LogError("File '%1' is too large (limit = %2)", filename, FmtDiskSize(max_len));
6429
6444
  return -1;
@@ -6512,19 +6527,10 @@ bool StreamReader::InitDecompressor(CompressionType type)
6512
6527
  return false;
6513
6528
  }
6514
6529
 
6515
- decompressor = func(this);
6516
-
6517
- if (!decompressor) {
6518
- error = true;
6519
- return false;
6520
- }
6521
- if (!decompressor->Init(type)) {
6522
- error = true;
6523
- return false;
6524
- }
6530
+ decoder = func(this, type);
6531
+ RG_ASSERT(decoder);
6525
6532
  }
6526
6533
 
6527
- compression_type = type;
6528
6534
  return true;
6529
6535
  }
6530
6536
 
@@ -6623,23 +6629,23 @@ void LineReader::PushLogFilter()
6623
6629
  char ctx_buf[1024];
6624
6630
 
6625
6631
  if (line_number > 0) {
6626
- Fmt(ctx_buf, "%1(%2)%3%4", st->GetFileName(), line_number, ctx ? ": " : "", ctx ? ctx : "");
6632
+ Fmt(ctx_buf, "%1%2(%3): ", ctx ? ctx : "", st->GetFileName(), line_number);
6627
6633
  } else {
6628
- Fmt(ctx_buf, "%1%2%3", st->GetFileName(), ctx ? ": " : "", ctx ? ctx : "");
6634
+ Fmt(ctx_buf, "%1%2: ", ctx ? ctx : "", st->GetFileName());
6629
6635
  }
6630
6636
 
6631
6637
  func(level, ctx_buf, msg);
6632
6638
  });
6633
6639
  }
6634
6640
 
6635
- #ifdef LZ4_VERSION_MAJOR
6636
- struct LZ4CompressContext {
6637
- LZ4F_cctx *encoder;
6638
- LZ4F_preferences_t prefs = {};
6641
+ void StreamWriter::SetEncoder(StreamEncoder *encoder)
6642
+ {
6643
+ RG_ASSERT(encoder);
6644
+ RG_ASSERT(!filename);
6645
+ RG_ASSERT(!this->encoder);
6639
6646
 
6640
- HeapArray<uint8_t> buf;
6641
- };
6642
- #endif
6647
+ this->encoder = encoder;
6648
+ }
6643
6649
 
6644
6650
  bool StreamWriter::Open(HeapArray<uint8_t> *mem, const char *filename,
6645
6651
  CompressionType compression_type, CompressionSpeed compression_speed)
@@ -6804,10 +6810,8 @@ bool StreamWriter::Write(Span<const uint8_t> buf)
6804
6810
  if (error) [[unlikely]]
6805
6811
  return false;
6806
6812
 
6807
- if (compressor) {
6808
- RG_ASSERT(compression_type != CompressionType::None);
6809
-
6810
- error |= !compressor->Write(buf);
6813
+ if (encoder) {
6814
+ error |= !encoder->Write(buf);
6811
6815
  return !error;
6812
6816
  } else {
6813
6817
  return WriteRaw(buf);
@@ -6819,11 +6823,11 @@ bool StreamWriter::Close(bool implicit)
6819
6823
  RG_ASSERT(implicit || this != &stdout_st);
6820
6824
  RG_ASSERT(implicit || this != &stderr_st);
6821
6825
 
6822
- if (compressor && !error) {
6823
- RG_ASSERT(compression_type != CompressionType::None);
6824
- error |= !compressor->Finalize();
6826
+ if (encoder) {
6827
+ error = error || !encoder->Finalize();
6825
6828
 
6826
- delete compressor;
6829
+ delete encoder;
6830
+ encoder = nullptr;
6827
6831
  }
6828
6832
 
6829
6833
  switch (dest.type) {
@@ -6882,7 +6886,6 @@ bool StreamWriter::Close(bool implicit)
6882
6886
 
6883
6887
  filename = nullptr;
6884
6888
  error = true;
6885
- compression_type = CompressionType::None;
6886
6889
  dest.type = DestinationType::Memory;
6887
6890
  str_alloc.ReleaseAll();
6888
6891
 
@@ -6900,21 +6903,10 @@ bool StreamWriter::InitCompressor(CompressionType type, CompressionSpeed speed)
6900
6903
  return false;
6901
6904
  }
6902
6905
 
6903
- compressor = func(this);
6904
-
6905
- if (!compressor) {
6906
- error = true;
6907
- return false;
6908
- }
6909
- if (!compressor->Init(type, speed)) {
6910
- error = true;
6911
- return false;
6912
- }
6906
+ encoder = func(this, type, speed);
6907
+ RG_ASSERT(encoder);
6913
6908
  }
6914
6909
 
6915
- compression_type = type;
6916
- compression_speed = speed;
6917
-
6918
6910
  return true;
6919
6911
  }
6920
6912
 
@@ -7015,14 +7007,14 @@ bool IsDecompressorAvailable(CompressionType compression_type)
7015
7007
  static bool CheckIniKey(Span<const char> key)
7016
7008
  {
7017
7009
  const auto test_char = [](char c) { return IsAsciiAlphaOrDigit(c) || c == '_' ||
7018
- c == '-' || c == '.' || c == '/'; };
7010
+ c == '-' || c == '.' || c == '/' || c == '@'; };
7019
7011
 
7020
7012
  if (!key.len) {
7021
7013
  LogError("INI key cannot be empty");
7022
7014
  return false;
7023
7015
  }
7024
7016
  if (!std::all_of(key.begin(), key.end(), test_char)) {
7025
- LogError("INI key must only contain alphanumeric, '.', '-' or '_' characters");
7017
+ LogError("INI key must only contain alphanumeric, '.', '-', '_', '/' or '@' characters");
7026
7018
  return false;
7027
7019
  }
7028
7020
 
@@ -7518,6 +7510,13 @@ void OptionParser::LogUnknownError() const
7518
7510
  }
7519
7511
  }
7520
7512
 
7513
+ void OptionParser::LogUnusedArguments() const
7514
+ {
7515
+ if (pos < args.len) {
7516
+ LogWarning("Unused command-line arguments");
7517
+ }
7518
+ }
7519
+
7521
7520
  // ------------------------------------------------------------------------
7522
7521
  // Console prompter (simplified readline)
7523
7522
  // ------------------------------------------------------------------------