xot 0.3.14 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f172e96fd93b17555e3ecb3c39e39bfdca41262542ac7a466da9d0447d0e40b
4
- data.tar.gz: 02107f5e7b765ad11b7dd4a68f501d5c952e8cde8e0b1b1b4f3e2fd40c605311
3
+ metadata.gz: 7e347867590b9d9d97a002320ac500f075dde62556b0944b2a35705b415e2806
4
+ data.tar.gz: c684375fa42a755e7cef817aad1c658fd26f484b515876cb35323e56e1c313bd
5
5
  SHA512:
6
- metadata.gz: 2049167fac1865e9aac0abe14692db36589471a30087711d35b7235f606173b21237fdb68864c3b00cb98367ad7f4f40f20ec7349273c86c5d725571c25d2f93
7
- data.tar.gz: 840c347e7a028850081974a24807bee0f88bc3833186f12a4f9615ba810c669313d4f7d42ebc277b086bebc976b4a26f3b9c4cd46fdd1c0715007c593e1a434c
6
+ metadata.gz: d94d2378ba6835df631dd21ef26140f3cc43af8c370478d7b7c6ce0e6e433fd08deafa45810970995942e3f1a1f04f4343894aa9ce5c5a276c60f442f1faf0de
7
+ data.tar.gz: 2dd7f8827dd1804be81babfe7b89410f41a96b280ac57f30724c67b63b3356a2ab71cddb4d10465e4ee49c34450d1e5f961dff24a84931a89a0bbf5f60159cda
@@ -26,8 +26,17 @@ jobs:
26
26
  - name: setup dependencies
27
27
  run: "ruby -I.github/workflows -rutils -e 'setup_dependencies'"
28
28
 
29
+ - name: packages
30
+ run: bundle exec rake packages
31
+
32
+ - name: setup zig
33
+ if: github.event.repository.name == 'reflex-terminal'
34
+ uses: mlugg/setup-zig@v2
35
+ with:
36
+ version: 0.16.0
37
+
29
38
  - name: test
30
- run: bundle exec rake packages test
39
+ run: bundle exec rake test
31
40
 
32
41
  - name: create gem
33
42
  id: gem
@@ -27,6 +27,15 @@ jobs:
27
27
  - name: packages
28
28
  run: bundle exec rake verbose packages
29
29
 
30
+ - name: setup zig
31
+ if: github.event.repository.name == 'reflex-terminal'
32
+ uses: mlugg/setup-zig@v2
33
+ with:
34
+ version: 0.16.0
35
+
36
+ - name: vendor
37
+ run: bundle exec rake vendor
38
+
30
39
  - name: lib
31
40
  run: bundle exec rake verbose lib
32
41
 
data/ChangeLog.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # xot ChangeLog
2
2
 
3
3
 
4
+ ## [v0.4.0] - 2026-08-04
5
+
6
+ - [BREAKING] Rework String conversions to std::wstring and CFString
7
+ - Add a String constructor taking a pointer and a size
8
+ - Add Xot.warn with a uniq option to suppress duplicate warnings
9
+ - Let a source raise _WIN32_WINNT above the Windows 7 baseline
10
+
11
+
12
+ ## [v0.3.15] - 2026-06-23
13
+
14
+ - Add WeakRef for weak references to RefCountable
15
+ - Compile vendored C sources with the C compiler
16
+
17
+
4
18
  ## [v0.3.14] - 2026-06-12
5
19
 
6
20
  - Link static archive explicitly in export_all_symbols on ucrt32
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.14
1
+ 0.4.0
data/include/xot/defs.h CHANGED
@@ -54,7 +54,7 @@ namespace Xot
54
54
  }// Types
55
55
 
56
56
 
57
- using namespace Types;
57
+ using namespace Xot::Types;
58
58
 
59
59
 
60
60
  }// Xot
data/include/xot/ref.h CHANGED
@@ -28,6 +28,28 @@ namespace Xot
28
28
  class EmptyClass {};
29
29
 
30
30
 
31
+ struct WeakRefCount : public NonCopyable
32
+ {
33
+
34
+ bool alive = true;
35
+
36
+ int ref_count = 1;
37
+
38
+ void retain ()
39
+ {
40
+ ++ref_count;
41
+ }
42
+
43
+ void release ()
44
+ {
45
+ assert(ref_count > 0);
46
+
47
+ if (--ref_count == 0) delete this;
48
+ }
49
+
50
+ };// WeakRefCount
51
+
52
+
31
53
  template <typename SuperClass = EmptyClass>
32
54
  class RefCountable : public SuperClass, public NonCopyable
33
55
  {
@@ -61,6 +83,12 @@ namespace Xot
61
83
  if (del) delete this;
62
84
  }
63
85
 
86
+ WeakRefCount* get_weak_ref_count ()
87
+ {
88
+ if (!wref_count) wref_count = new WeakRefCount();
89
+ return wref_count;
90
+ }
91
+
64
92
  virtual void* rucy_wrapper_value () const
65
93
  {
66
94
  return NULL;
@@ -86,12 +114,20 @@ namespace Xot
86
114
 
87
115
  virtual ~RefCountable ()
88
116
  {
117
+ if (wref_count)
118
+ {
119
+ wref_count->alive = false;
120
+ wref_count->release();
121
+ wref_count = NULL;
122
+ }
89
123
  }
90
124
 
91
125
  private:
92
126
 
93
127
  mutable int refc_count = 0;
94
128
 
129
+ WeakRefCount* wref_count = NULL;
130
+
95
131
  int refc_update_count (bool increment) const
96
132
  {
97
133
  int c = refc_count + (increment ? +1 : -1);
@@ -304,6 +340,115 @@ namespace Xot
304
340
  };// Ref
305
341
 
306
342
 
343
+ template <typename T>
344
+ class WeakRef
345
+ {
346
+
347
+ typedef WeakRef<T> This;
348
+
349
+ typedef T Value;
350
+
351
+ typedef const T ConstValue;
352
+
353
+ typedef T& Reference;
354
+
355
+ typedef const T& ConstReference;
356
+
357
+ typedef T* Pointer;
358
+
359
+ typedef const T* ConstPointer;
360
+
361
+ public:
362
+
363
+ WeakRef (Pointer ptr = NULL)
364
+ {
365
+ reset(ptr);
366
+ }
367
+
368
+ WeakRef (const This& obj)
369
+ {
370
+ reset(obj.ptr, obj.wref_count);
371
+ }
372
+
373
+ This& operator = (Pointer ptr)
374
+ {
375
+ reset(ptr);
376
+ return *this;
377
+ }
378
+
379
+ This& operator = (const This& obj)
380
+ {
381
+ if (&obj != this) reset(obj.ptr, obj.wref_count);
382
+ return *this;
383
+ }
384
+
385
+ ~WeakRef ()
386
+ {
387
+ if (wref_count) wref_count->release();
388
+ }
389
+
390
+ void reset (Pointer ptr = NULL)
391
+ {
392
+ reset(ptr, ptr ? ptr->get_weak_ref_count() : NULL);
393
+ }
394
+
395
+ Pointer get () {return wref_count && wref_count->alive ? ptr : NULL;}
396
+
397
+ ConstPointer get () const {return wref_count && wref_count->alive ? ptr : NULL;}
398
+
399
+ Pointer operator -> () {return get();}
400
+
401
+ ConstPointer operator -> () const {return get();}
402
+
403
+ Reference operator * () {return *get();}
404
+
405
+ ConstReference operator * () const {return *get();}
406
+
407
+ operator Pointer () {return get();}
408
+
409
+ operator ConstPointer () const {return get();}
410
+
411
+ bool operator == (Pointer ptr) const {return get() == ptr;}
412
+
413
+ bool operator != (Pointer ptr) const {return !operator==(ptr);}
414
+
415
+ bool operator == (ConstPointer ptr) const {return get() == ptr;}
416
+
417
+ bool operator != (ConstPointer ptr) const {return !operator==(ptr);}
418
+
419
+ bool operator == (const This& obj) const {return get() == obj.get();}
420
+
421
+ bool operator != (const This& obj) const {return !operator==(obj);}
422
+
423
+ template <typename X>
424
+ bool operator == (const WeakRef<X>& obj) const {return get() == obj.get();}
425
+
426
+ template <typename X>
427
+ bool operator != (const WeakRef<X>& obj) const {return !operator==(obj);}
428
+
429
+ bool operator < (const This& obj) const {return get() < obj.get();}
430
+
431
+ operator bool () const {return get();}
432
+
433
+ bool operator ! () const {return !operator bool();}
434
+
435
+ private:
436
+
437
+ void reset (Pointer ptr, WeakRefCount* count)
438
+ {
439
+ if (count) count->retain();
440
+ if (wref_count) wref_count->release();
441
+ this->ptr = ptr;
442
+ this->wref_count = count;
443
+ }
444
+
445
+ Pointer ptr = NULL;
446
+
447
+ WeakRefCount* wref_count = NULL;
448
+
449
+ };// WeakRef
450
+
451
+
307
452
  }// Xot
308
453
 
309
454
 
data/include/xot/string.h CHANGED
@@ -26,7 +26,9 @@
26
26
 
27
27
 
28
28
  #if defined(OSX) || defined(IOS)
29
- struct __CFString;
29
+
30
+ struct __CFString;
31
+
30
32
  #endif
31
33
 
32
34
 
@@ -34,6 +36,13 @@ namespace Xot
34
36
  {
35
37
 
36
38
 
39
+ #if defined(OSX) || defined(IOS)
40
+
41
+ typedef std::shared_ptr<const __CFString> CFStringPtr;
42
+
43
+ #endif
44
+
45
+
37
46
  class String : public std::string
38
47
  {
39
48
 
@@ -45,6 +54,8 @@ namespace Xot
45
54
 
46
55
  String (const char* str);
47
56
 
57
+ String (const char* str, size_t size);
58
+
48
59
  String (const std::string& str);
49
60
 
50
61
  template <typename ITERATOR>
@@ -64,6 +75,18 @@ namespace Xot
64
75
 
65
76
  friend String operator + (const char* lhs, const String& rhs);
66
77
 
78
+ #if defined(OSX) || defined(IOS)
79
+
80
+ CFStringPtr to_cfstr () const;
81
+
82
+ #elif defined(WIN32)
83
+
84
+ String (const wchar_t* str, size_t size);
85
+
86
+ std::wstring to_wstr () const;
87
+
88
+ #endif
89
+
67
90
  };// String
68
91
 
69
92
 
@@ -79,15 +102,6 @@ namespace Xot
79
102
  template <typename T> String to_s (const T& val);
80
103
 
81
104
 
82
- #if defined(OSX) || defined(IOS)
83
-
84
- typedef std::shared_ptr<const __CFString> CFStringPtr;
85
-
86
- CFStringPtr cfstring (const char* str);
87
-
88
- #endif
89
-
90
-
91
105
  }// Xot
92
106
 
93
107
 
@@ -6,7 +6,11 @@
6
6
 
7
7
  #ifdef WIN32
8
8
  #undef _WIN32_WINNT
9
- #define _WIN32_WINNT _WIN32_WINNT_WIN7
9
+ #ifdef XOT_WIN32_WINNT
10
+ #define _WIN32_WINNT XOT_WIN32_WINNT
11
+ #else
12
+ #define _WIN32_WINNT _WIN32_WINNT_WIN7
13
+ #endif
10
14
  #include <windows.h>
11
15
  #include <windowsx.h>
12
16
  #endif
data/lib/xot/extconf.rb CHANGED
@@ -51,8 +51,8 @@ module Xot
51
51
  local_libs << 'stdc++' if gcc?
52
52
 
53
53
  $CPPFLAGS = make_cppflags $CPPFLAGS, defs, inc_dirs
54
- $CFLAGS = make_cflags $CFLAGS + ' -x c++'
55
- $CXXFLAGS = make_cflags $CXXFLAGS + ' -x c++' if $CXXFLAGS
54
+ $CFLAGS = make_cxxflags $CFLAGS + ' -x c++'
55
+ $CXXFLAGS = make_cxxflags $CXXFLAGS + ' -x c++' if $CXXFLAGS
56
56
  $LDFLAGS = make_ldflags ldflags, lib_dirs, frameworks
57
57
  $LOCAL_LIBS << local_libs.reverse.map {|s| " -l#{s}"}.join
58
58
  end
data/lib/xot/extension.rb CHANGED
@@ -6,7 +6,7 @@ module Xot
6
6
  module_function
7
7
 
8
8
  def name(downcase = false)
9
- super().split('::')[-2].then {|s|
9
+ super().split('::')[..-2].join.then {|s|
10
10
  downcase ? s.gsub(/([a-z])([A-Z])/) {"#{$1}-#{$2}"}.downcase : s
11
11
  }
12
12
  end
data/lib/xot/rake/util.rb CHANGED
@@ -213,22 +213,28 @@ module Xot
213
213
  [root, RbConfig::CONFIG['rubyarchhdrdir'] || "#{root}/#{RUBY_PLATFORM}"]
214
214
  end
215
215
 
216
- def make_cflags(flags = '')
217
- warning_opts = %w[no-unknown-pragmas]
218
- warning_opts += %w[
216
+ def make_cflags(flags = '', std: 'gnu17', stdlib: nil)
217
+ warn_opts = %w[no-unknown-pragmas]
218
+ warn_opts += %w[
219
219
  no-deprecated-register
220
220
  no-reserved-user-defined-literal
221
221
  ] if clang?
222
+
222
223
  s = flags.dup
223
- s << warning_opts.map {|s| " -W#{s}"}.join
224
- s << " -arch arm64" if osx? && arm64?
225
- s << ' -std=c++20' if gcc? || emcc?
226
- s << ' -std=c++20 -stdlib=libc++ -mmacosx-version-min=10.10' if clang?
227
- s << ' ' + RbConfig::CONFIG['debugflags'] if debug?
228
- s.gsub!(/-O\d?\w*/, '-O0') if debug?
224
+ s << " -arch arm64" if osx? && arm64?
225
+ s << " -std=#{std}" if clang? || gcc? || emcc?
226
+ s << " -stdlib=#{stdlib}" if clang? && stdlib
227
+ s << ' -mmacosx-version-min=10.10' if clang? && osx?
228
+ s << ' ' + RbConfig::CONFIG['debugflags'] if debug?
229
+ s.gsub!(/-O\d?\w*/, '-O0') if debug?
230
+ s << warn_opts.map {|s| " -W#{s}"}.join
229
231
  s
230
232
  end
231
233
 
234
+ def make_cxxflags(flags = '')
235
+ make_cflags flags, std: 'c++20', stdlib: 'libc++'
236
+ end
237
+
232
238
  def make_ldflags(flags = '', libdirs = [], frameworks = [])
233
239
  s = flags.dup
234
240
  s << libdirs.map {|s| " -L#{s}"}.join
@@ -242,11 +248,17 @@ module Xot
242
248
  make_cppflags flags, defs, inc_dirs
243
249
  end
244
250
 
251
+ def cflags(warnings = true)
252
+ cflags = get_env :CFLAGS, RbConfig::CONFIG['CFLAGS']
253
+ cflags = cflags.gsub(/-W[\w\-\=]+/, '') + ' -w' unless warnings
254
+ make_cflags cflags
255
+ end
256
+
245
257
  def cxxflags(warnings = true)
246
258
  cflags = get_env :CFLAGS, RbConfig::CONFIG['CFLAGS']
247
259
  cxxflags = get_env :CXXFLAGS, RbConfig::CONFIG['CXXFLAGS']
248
260
  cflags = cflags.gsub(/-W[\w\-\=]+/, '') + ' -w' unless warnings
249
- make_cflags "#{cflags} #{cxxflags}"
261
+ make_cxxflags "#{cflags} #{cxxflags}"
250
262
  end
251
263
 
252
264
  def arflags()
data/lib/xot/rake.rb CHANGED
@@ -327,7 +327,11 @@ module Xot
327
327
  unless get_env :VENDOR_NOCOMPILE, false
328
328
  vendor_srcs_map(*srcdirs).each do |src, obj|
329
329
  rake_puts "compiling #{src}"
330
- sh %( #{cxx} -c #{cppflags} #{cxxflags false} -o #{obj} #{src} )
330
+ if File.extname(src) == '.c'
331
+ sh %( #{cc} -c #{cppflags} #{cflags false} -o #{obj} #{src} )
332
+ else
333
+ sh %( #{cxx} -c #{cppflags} #{cxxflags false} -o #{obj} #{src} )
334
+ end
331
335
  end
332
336
  end
333
337
  end
data/lib/xot/util.rb CHANGED
@@ -6,6 +6,15 @@ module Xot
6
6
 
7
7
  extend module Util
8
8
 
9
+ def warn(message, uniq: false)
10
+ if uniq
11
+ @warnings__ ||= {}
12
+ return if @warnings__[message]
13
+ @warnings__[message] = true
14
+ end
15
+ Kernel.warn message
16
+ end
17
+
9
18
  def get_env!(name, defval = nil)
10
19
  val = ENV[name.to_s] || Object.const_get(name) rescue defval
11
20
  val.dup rescue val
data/src/string.cpp CHANGED
@@ -1,13 +1,16 @@
1
1
  #include "xot/string.h"
2
2
 
3
3
 
4
+ #include <limits.h>
4
5
  #include <stdio.h>
5
6
  #include <string.h>
6
7
  #include <algorithm>
7
8
  #include "xot/exception.h"
8
9
 
9
10
  #if defined(OSX) || defined(IOS)
10
- #import <CoreFoundation/CoreFoundation.h>
11
+ #import <CoreFoundation/CoreFoundation.h>
12
+ #elif defined(WIN32)
13
+ #include "xot/windows.h"
11
14
  #endif
12
15
 
13
16
 
@@ -24,6 +27,11 @@ namespace Xot
24
27
  {
25
28
  }
26
29
 
30
+ String::String (const char* str, size_t size)
31
+ : Super(str, size)
32
+ {
33
+ }
34
+
27
35
  String::String (const std::string& str)
28
36
  : Super(str)
29
37
  {
@@ -88,6 +96,57 @@ namespace Xot
88
96
  return t;
89
97
  }
90
98
 
99
+ #if defined(OSX) || defined(IOS)
100
+
101
+ static void
102
+ release_cfstring (CFTypeRef ref)
103
+ {
104
+ if (ref) CFRelease(ref);
105
+ }
106
+
107
+ CFStringPtr
108
+ String::to_cfstr () const
109
+ {
110
+ return CFStringPtr(
111
+ CFStringCreateWithCString(kCFAllocatorDefault, c_str(), kCFStringEncodingUTF8),
112
+ release_cfstring);
113
+ }
114
+
115
+ #elif defined(WIN32)
116
+
117
+ String::String (const wchar_t* str, size_t size)
118
+ {
119
+ if (size > INT_MAX)
120
+ argument_error(__FILE__, __LINE__);
121
+ if (!str || size == 0) return;
122
+
123
+ int len = WideCharToMultiByte(CP_UTF8, 0, str, (int) size, NULL, 0, NULL, NULL);
124
+ if (len <= 0) system_error(__FILE__, __LINE__);
125
+
126
+ resize((size_t) len);
127
+ WideCharToMultiByte(CP_UTF8, 0, str, (int) size, &(*this)[0], len, NULL, NULL);
128
+ }
129
+
130
+ std::wstring
131
+ String::to_wstr () const
132
+ {
133
+ if (empty()) return std::wstring();
134
+
135
+ size_t size = this->size();
136
+ if (size > INT_MAX)
137
+ invalid_state_error(__FILE__, __LINE__);
138
+
139
+ int len = MultiByteToWideChar(CP_UTF8, 0, data(), (int) size, NULL, 0);
140
+ if (len <= 0) system_error(__FILE__, __LINE__);
141
+
142
+ std::wstring result;
143
+ result.resize((size_t) len);
144
+ MultiByteToWideChar(CP_UTF8, 0, data(), (int) size, &result[0], len);
145
+ return result;
146
+ }
147
+
148
+ #endif
149
+
91
150
 
92
151
  String
93
152
  stringf (const char* format, ...)
@@ -199,21 +258,6 @@ namespace Xot
199
258
  return to_s((CFStringRef) val.get());
200
259
  }
201
260
 
202
-
203
- static void
204
- release_cfstring (CFTypeRef ref)
205
- {
206
- if (ref) CFRelease(ref);
207
- }
208
-
209
- CFStringPtr
210
- cfstring (const char* str)
211
- {
212
- CFStringRef ref = CFStringCreateWithCString(
213
- kCFAllocatorDefault, str, kCFStringEncodingUTF8);
214
- return CFStringPtr(ref, release_cfstring);
215
- }
216
-
217
261
  #endif
218
262
 
219
263
 
data/test/test_util.rb ADDED
@@ -0,0 +1,33 @@
1
+ require_relative 'helper'
2
+ require 'stringio'
3
+
4
+
5
+ class TestUtil < Test::Unit::TestCase
6
+
7
+ def util()
8
+ Object.new.extend Xot::Util
9
+ end
10
+
11
+ def capture_stderr(&block)
12
+ stderr, $stderr = $stderr, StringIO.new
13
+ block.call
14
+ $stderr.string
15
+ ensure
16
+ $stderr = stderr
17
+ end
18
+
19
+ def test_warn()
20
+ u = util
21
+ assert_equal "x\nx\n", capture_stderr {u.warn "x"; u.warn "x"}
22
+ end
23
+
24
+ def test_warn_uniq()
25
+ u = util
26
+ assert_equal "x\ny\n", capture_stderr {
27
+ u.warn "x", uniq: true
28
+ u.warn "x", uniq: true
29
+ u.warn "y", uniq: true
30
+ }
31
+ end
32
+
33
+ end# TestUtil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.14
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - xordog
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-12 00:00:00.000000000 Z
11
+ date: 2026-08-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This library include some useful utility classes and functions for development
14
14
  with C++.
@@ -81,6 +81,7 @@ files:
81
81
  - test/test_setter.rb
82
82
  - test/test_tester.rb
83
83
  - test/test_universal_accessor.rb
84
+ - test/test_util.rb
84
85
  - xot.gemspec
85
86
  homepage: https://github.com/xord/xot
86
87
  licenses:
@@ -119,3 +120,4 @@ test_files:
119
120
  - test/test_setter.rb
120
121
  - test/test_tester.rb
121
122
  - test/test_universal_accessor.rb
123
+ - test/test_util.rb