sfml3-rb 0.2.2 → 0.3.1

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.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +67 -16
  4. data/README.md +123 -32
  5. data/TODO.md +18 -11
  6. data/ext/audio/audio_enums.c +58 -20
  7. data/ext/audio/listener.c +89 -6
  8. data/ext/audio/music.c +212 -5
  9. data/ext/audio/sound.c +218 -9
  10. data/ext/audio/sound_buffer.c +197 -47
  11. data/ext/audio/sound_buffer_recorder.c +90 -18
  12. data/ext/audio/sound_recorder.c +188 -58
  13. data/ext/audio/sound_source_cone.c +127 -33
  14. data/ext/audio/sound_stream.c +204 -21
  15. data/ext/core/exceptions.c +10 -8
  16. data/ext/core/unicode.c +12 -2
  17. data/ext/ext.c +8 -0
  18. data/ext/graphics/blend_mode.c +218 -60
  19. data/ext/graphics/circle.c +300 -16
  20. data/ext/graphics/color.c +253 -94
  21. data/ext/graphics/drawable.c +16 -4
  22. data/ext/graphics/font.c +144 -25
  23. data/ext/graphics/glyph.c +38 -8
  24. data/ext/graphics/image.c +205 -41
  25. data/ext/graphics/polygon.c +317 -30
  26. data/ext/graphics/rect.c +225 -60
  27. data/ext/graphics/rectangle.c +307 -35
  28. data/ext/graphics/render_state.c +124 -12
  29. data/ext/graphics/render_texture.c +191 -14
  30. data/ext/graphics/render_window.c +55 -0
  31. data/ext/graphics/render_window.h +10 -0
  32. data/ext/graphics/shader.c +289 -17
  33. data/ext/graphics/shape.c +265 -32
  34. data/ext/graphics/sprite.c +245 -30
  35. data/ext/graphics/stencil_mode.c +163 -46
  36. data/ext/graphics/target.c +121 -43
  37. data/ext/graphics/target.h +31 -17
  38. data/ext/graphics/text.c +339 -19
  39. data/ext/graphics/texture.c +291 -6
  40. data/ext/graphics/transform.c +178 -5
  41. data/ext/graphics/transformable.c +127 -12
  42. data/ext/graphics/vertex.c +98 -6
  43. data/ext/graphics/vertex_array.c +142 -21
  44. data/ext/graphics/vertex_buffer.c +154 -12
  45. data/ext/graphics/view.c +140 -6
  46. data/ext/network/ftp.c +278 -12
  47. data/ext/network/http.c +179 -44
  48. data/ext/network/ip_address.c +127 -35
  49. data/ext/network/network_enums.c +248 -141
  50. data/ext/network/packet.c +280 -41
  51. data/ext/network/socket_selector.c +98 -21
  52. data/ext/network/tcp_listener.c +82 -18
  53. data/ext/network/tcp_socket.c +135 -27
  54. data/ext/network/udp_socket.c +129 -28
  55. data/ext/ports.rb +7 -0
  56. data/ext/system/buffer.c +47 -16
  57. data/ext/system/clock.c +77 -12
  58. data/ext/system/input_stream.c +113 -51
  59. data/ext/system/sleep.c +10 -2
  60. data/ext/system/time.c +182 -40
  61. data/ext/system/vec2.c +166 -39
  62. data/ext/system/vec3.c +177 -39
  63. data/ext/window/clipboard.c +47 -17
  64. data/ext/window/context.c +66 -13
  65. data/ext/window/context_settings.c +132 -42
  66. data/ext/window/cursor.c +45 -9
  67. data/ext/window/event.c +164 -53
  68. data/ext/window/joystick.c +69 -3
  69. data/ext/window/keyboard.c +168 -116
  70. data/ext/window/mouse.c +64 -13
  71. data/ext/window/sensor.c +28 -2
  72. data/ext/window/touch.c +32 -12
  73. data/ext/window/video_mode.c +93 -31
  74. data/ext/window/vulkan.c +34 -6
  75. data/ext/window/window.c +228 -229
  76. data/ext/window/window.h +4 -4
  77. data/ext/window/window_base.c +251 -0
  78. data/ext/window/window_base.h +43 -0
  79. data/ext/window/window_base.inc +236 -0
  80. data/lib/sfml/version.rb +1 -1
  81. data/sig/audio/audio_enums.rbs +30 -0
  82. data/sig/audio/listener.rbs +16 -0
  83. data/sig/audio/music.rbs +56 -0
  84. data/sig/audio/sound.rbs +51 -0
  85. data/sig/audio/sound_buffer.rbs +17 -0
  86. data/sig/audio/sound_buffer_recorder.rbs +14 -0
  87. data/sig/audio/sound_recorder.rbs +17 -0
  88. data/sig/audio/sound_source_cone.rbs +14 -0
  89. data/sig/audio/sound_stream.rbs +51 -0
  90. data/sig/graphics/blend_mode.rbs +29 -0
  91. data/sig/graphics/circle.rbs +44 -0
  92. data/sig/graphics/color.rbs +39 -0
  93. data/sig/graphics/drawable.rbs +5 -0
  94. data/sig/graphics/font.rbs +20 -0
  95. data/sig/graphics/glyph.rbs +7 -0
  96. data/sig/graphics/image.rbs +22 -0
  97. data/sig/graphics/polygon.rbs +42 -0
  98. data/sig/graphics/rect.rbs +33 -0
  99. data/sig/graphics/rectangle.rbs +42 -0
  100. data/sig/graphics/render_state.rbs +21 -0
  101. data/sig/graphics/render_target.rbs +18 -0
  102. data/sig/graphics/render_texture.rbs +39 -0
  103. data/sig/graphics/render_window.rbs +7 -0
  104. data/sig/graphics/shader.rbs +39 -0
  105. data/sig/graphics/shape.rbs +38 -0
  106. data/sig/graphics/sprite.rbs +34 -0
  107. data/sig/graphics/stencil_mode.rbs +18 -0
  108. data/sig/graphics/target.rbs +8 -0
  109. data/sig/graphics/text.rbs +48 -0
  110. data/sig/graphics/texture.rbs +34 -0
  111. data/sig/graphics/transform.rbs +37 -0
  112. data/sig/graphics/transformable.rbs +25 -0
  113. data/sig/graphics/vertex.rbs +17 -0
  114. data/sig/graphics/vertex_array.rbs +17 -0
  115. data/sig/graphics/vertex_buffer.rbs +22 -0
  116. data/sig/graphics/view.rbs +23 -0
  117. data/sig/network/ftp.rbs +46 -0
  118. data/sig/network/http.rbs +27 -0
  119. data/sig/network/ip_address.rbs +22 -0
  120. data/sig/network/network_enums.rbs +95 -0
  121. data/sig/network/packet.rbs +40 -0
  122. data/sig/network/socket_selector.rbs +14 -0
  123. data/sig/network/tcp_listener.rbs +13 -0
  124. data/sig/network/tcp_socket.rbs +18 -0
  125. data/sig/network/udp_socket.rbs +17 -0
  126. data/sig/sfml/version.rbs +3 -0
  127. data/sig/system/buffer.rbs +11 -0
  128. data/sig/system/clock.rbs +13 -0
  129. data/sig/system/input_stream.rbs +7 -0
  130. data/sig/system/sleep.rbs +3 -0
  131. data/sig/system/time.rbs +28 -0
  132. data/sig/system/vec2.rbs +26 -0
  133. data/sig/system/vec3.rbs +27 -0
  134. data/sig/window/clipboard.rbs +8 -0
  135. data/sig/window/context.rbs +11 -0
  136. data/sig/window/context_settings.rbs +20 -0
  137. data/sig/window/cursor.rbs +6 -0
  138. data/sig/window/event.rbs +20 -0
  139. data/sig/window/joystick.rbs +15 -0
  140. data/sig/window/keyboard.rbs +10 -0
  141. data/sig/window/mouse.rbs +9 -0
  142. data/sig/window/sensor.rbs +8 -0
  143. data/sig/window/touch.rbs +6 -0
  144. data/sig/window/video_mode.rbs +16 -0
  145. data/sig/window/vulkan.rbs +7 -0
  146. data/sig/window/window.rbs +34 -0
  147. data/sig/window/window_base.rbs +33 -0
  148. metadata +76 -3
@@ -9,13 +9,13 @@
9
9
  #include "network/tcp_socket.h"
10
10
 
11
11
  typedef struct {
12
- sfTcpListener *handle;
12
+ sfTcpListener* handle;
13
13
  } TcpListener;
14
14
 
15
15
  static VALUE rb_cTcpListener;
16
16
 
17
- static void TcpListener_free(void *ptr) {
18
- TcpListener *listener = ptr;
17
+ static void TcpListener_free(void* ptr) {
18
+ TcpListener* listener = ptr;
19
19
 
20
20
  if (listener->handle != NULL) {
21
21
  sfTcpListener_destroy(listener->handle);
@@ -27,11 +27,10 @@ static void TcpListener_free(void *ptr) {
27
27
  static const rb_data_type_t TcpListener_data_type = {
28
28
  .wrap_struct_name = "SFML::TcpListener",
29
29
  .function = {.dmark = NULL, .dfree = TcpListener_free, .dsize = NULL},
30
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
31
- };
30
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
32
31
 
33
- static VALUE TcpListener_wrap(VALUE klass, sfTcpListener *handle) {
34
- TcpListener *ptr;
32
+ static VALUE TcpListener_wrap(VALUE klass, sfTcpListener* handle) {
33
+ TcpListener* ptr;
35
34
 
36
35
  if (handle == NULL) {
37
36
  rb_raise(rb_eRuntimeError, "failed to create TCP listener");
@@ -43,44 +42,104 @@ static VALUE TcpListener_wrap(VALUE klass, sfTcpListener *handle) {
43
42
  return TypedData_Wrap_Struct(klass, &TcpListener_data_type, ptr);
44
43
  }
45
44
 
46
- static VALUE TcpListener_new(VALUE klass) {
45
+ static VALUE TcpListener_alloc(VALUE klass) {
47
46
  return TcpListener_wrap(klass, sfTcpListener_create());
48
47
  }
49
48
 
49
+ /* call-seq:
50
+ * TcpListener.new -> TcpListener
51
+ *
52
+ * Creates a new TCP listener that is not yet listening.
53
+ *
54
+ * @return [TcpListener]
55
+ */
56
+ static VALUE TcpListener_initialize(VALUE self) {
57
+ return self;
58
+ }
59
+
60
+ /* call-seq:
61
+ * TcpListener.any_port -> Integer
62
+ *
63
+ * Returns the port value that makes #listen bind to an OS-chosen port.
64
+ *
65
+ * @return [Integer] a port value that #listen interprets as "let the OS
66
+ * pick an available port"
67
+ */
50
68
  static VALUE TcpListener_any_port(VALUE klass) {
51
69
  return UINT2NUM(sfTcpListener_anyPort());
52
70
  }
53
71
 
72
+ /* call-seq: blocking? -> true or false
73
+ *
74
+ * Returns +true+ if the listener is in blocking mode.
75
+ *
76
+ * @return [Boolean]
77
+ */
54
78
  static VALUE TcpListener_blocking(VALUE self) {
55
79
  return BOOL2RB(sfTcpListener_isBlocking(Get_TcpListener_Struct(self)));
56
80
  }
57
81
 
82
+ /* call-seq:
83
+ * blocking=(value) -> value
84
+ *
85
+ * Enables or disables blocking mode according to +value+.
86
+ *
87
+ * @return [Boolean] +value+
88
+ */
58
89
  static VALUE TcpListener_set_blocking(VALUE self, VALUE rb_value) {
59
90
  sfTcpListener_setBlocking(Get_TcpListener_Struct(self), RTEST(rb_value));
60
91
  return rb_value;
61
92
  }
62
93
 
94
+ /* call-seq: local_port -> Integer
95
+ *
96
+ * Returns the port the listener is bound to, or 0 if it isn't listening.
97
+ *
98
+ * @return [Integer] the port the listener is bound to, or 0 if it isn't
99
+ * listening
100
+ */
63
101
  static VALUE TcpListener_local_port(VALUE self) {
64
102
  return UINT2NUM(sfTcpListener_getLocalPort(Get_TcpListener_Struct(self)));
65
103
  }
66
104
 
67
- static VALUE TcpListener_listen(int argc, VALUE *argv, VALUE self) {
105
+ /* call-seq:
106
+ * listen(port, address = IpAddress::ANY) -> Symbol
107
+ *
108
+ * Starts listening for incoming connections on +port+, optionally
109
+ * restricted to a specific local network interface via +address+.
110
+ *
111
+ * @return [Symbol] a SocketStatus name, +:done+ on success
112
+ */
113
+ static VALUE TcpListener_listen(int argc, VALUE* argv, VALUE self) {
68
114
  VALUE rb_port, rb_address;
69
115
 
70
116
  rb_scan_args(argc, argv, "11", &rb_port, &rb_address);
71
117
 
72
- return ID2SYM(rb_intern(socket_status_name(sfTcpListener_listen(
73
- Get_TcpListener_Struct(self), (unsigned short) NUM2INT(rb_port),
74
- ip_address_from_rb(rb_address, sfIpAddress_Any)))));
118
+ return ID2SYM(rb_intern(socket_status_name(
119
+ sfTcpListener_listen(Get_TcpListener_Struct(self), (unsigned short)NUM2INT(rb_port),
120
+ ip_address_from_rb(rb_address, sfIpAddress_Any)))));
75
121
  }
76
122
 
123
+ /* call-seq: close -> self
124
+ *
125
+ * Stops listening and closes the underlying socket.
126
+ *
127
+ * @return [self]
128
+ */
77
129
  static VALUE TcpListener_close(VALUE self) {
78
130
  sfTcpListener_close(Get_TcpListener_Struct(self));
79
131
  return self;
80
132
  }
81
133
 
134
+ /* call-seq: accept -> [TcpSocket, Symbol]
135
+ *
136
+ * Blocks (unless #blocking? is +false+) waiting for a client to connect.
137
+ *
138
+ * @return [Array(TcpSocket, Symbol)] the connected socket (or +nil+ if the
139
+ * status isn't +:done+), and a SocketStatus name
140
+ */
82
141
  static VALUE TcpListener_accept(VALUE self) {
83
- sfTcpSocket *socket = NULL;
142
+ sfTcpSocket* socket = NULL;
84
143
  sfSocketStatus status = sfTcpListener_accept(Get_TcpListener_Struct(self), &socket);
85
144
  VALUE rb_result = rb_ary_new_capa(2);
86
145
 
@@ -90,10 +149,15 @@ static VALUE TcpListener_accept(VALUE self) {
90
149
  return rb_result;
91
150
  }
92
151
 
93
- void Init_TcpListener(VALUE rb_module) {
94
- rb_cTcpListener = rb_define_class_under(rb_module, "TcpListener", rb_cObject);
152
+ /* Document-class: SFML::TcpListener
153
+ * Listens for and accepts incoming TCP connections, producing connected
154
+ * TcpSocket instances.
155
+ */
156
+ void Init_TcpListener(VALUE rb_mSFML) {
157
+ rb_cTcpListener = rb_define_class_under(rb_mSFML, "TcpListener", rb_cObject);
158
+ rb_define_alloc_func(rb_cTcpListener, TcpListener_alloc);
95
159
 
96
- rb_define_singleton_method(rb_cTcpListener, "new", TcpListener_new, 0);
160
+ rb_define_method(rb_cTcpListener, "initialize", TcpListener_initialize, 0);
97
161
  rb_define_singleton_method(rb_cTcpListener, "any_port", TcpListener_any_port, 0);
98
162
 
99
163
  rb_define_method(rb_cTcpListener, "blocking?", TcpListener_blocking, 0);
@@ -108,8 +172,8 @@ VALUE Get_Klass_TcpListener(void) {
108
172
  return rb_cTcpListener;
109
173
  }
110
174
 
111
- void *Get_TcpListener_Struct(VALUE self) {
112
- TcpListener *ptr;
175
+ void* Get_TcpListener_Struct(VALUE self) {
176
+ TcpListener* ptr;
113
177
  TypedData_Get_Struct(self, TcpListener, &TcpListener_data_type, ptr);
114
178
  return ptr->handle;
115
179
  }
@@ -10,13 +10,13 @@
10
10
  #include "system/time.h"
11
11
 
12
12
  typedef struct {
13
- sfTcpSocket *handle;
13
+ sfTcpSocket* handle;
14
14
  } TcpSocket;
15
15
 
16
16
  static VALUE rb_cTcpSocket;
17
17
 
18
- static void TcpSocket_free(void *ptr) {
19
- TcpSocket *socket = ptr;
18
+ static void TcpSocket_free(void* ptr) {
19
+ TcpSocket* socket = ptr;
20
20
 
21
21
  if (socket->handle != NULL) {
22
22
  sfTcpSocket_destroy(socket->handle);
@@ -28,11 +28,10 @@ static void TcpSocket_free(void *ptr) {
28
28
  static const rb_data_type_t TcpSocket_data_type = {
29
29
  .wrap_struct_name = "SFML::TcpSocket",
30
30
  .function = {.dmark = NULL, .dfree = TcpSocket_free, .dsize = NULL},
31
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
32
- };
31
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
33
32
 
34
- static VALUE TcpSocket_wrap(VALUE klass, sfTcpSocket *handle) {
35
- TcpSocket *ptr;
33
+ static VALUE TcpSocket_wrap(VALUE klass, sfTcpSocket* handle) {
34
+ TcpSocket* ptr;
36
35
 
37
36
  if (handle == NULL) {
38
37
  rb_raise(rb_eRuntimeError, "failed to create TCP socket");
@@ -44,36 +43,88 @@ static VALUE TcpSocket_wrap(VALUE klass, sfTcpSocket *handle) {
44
43
  return TypedData_Wrap_Struct(klass, &TcpSocket_data_type, ptr);
45
44
  }
46
45
 
47
- VALUE tcp_socket_from_handle(sfTcpSocket *socket) {
46
+ VALUE tcp_socket_from_handle(sfTcpSocket* socket) {
48
47
  return TcpSocket_wrap(rb_cTcpSocket, socket);
49
48
  }
50
49
 
51
- static VALUE TcpSocket_new(VALUE klass) {
50
+ static VALUE TcpSocket_alloc(VALUE klass) {
52
51
  return TcpSocket_wrap(klass, sfTcpSocket_create());
53
52
  }
54
53
 
54
+ /* call-seq:
55
+ * TcpSocket.new -> TcpSocket
56
+ *
57
+ * Creates a new, unconnected TCP socket.
58
+ *
59
+ * @return [TcpSocket] a new, unconnected socket
60
+ */
61
+ static VALUE TcpSocket_initialize(VALUE self) {
62
+ return self;
63
+ }
64
+
65
+ /* call-seq: blocking? -> true or false
66
+ *
67
+ * Returns +true+ if the socket is in blocking mode.
68
+ *
69
+ * @return [Boolean]
70
+ */
55
71
  static VALUE TcpSocket_blocking(VALUE self) {
56
72
  return BOOL2RB(sfTcpSocket_isBlocking(Get_TcpSocket_Struct(self)));
57
73
  }
58
74
 
75
+ /* call-seq:
76
+ * blocking=(value) -> value
77
+ *
78
+ * Enables or disables blocking mode according to +value+.
79
+ *
80
+ * @return [Boolean] +value+
81
+ */
59
82
  static VALUE TcpSocket_set_blocking(VALUE self, VALUE rb_value) {
60
83
  sfTcpSocket_setBlocking(Get_TcpSocket_Struct(self), RTEST(rb_value));
61
84
  return rb_value;
62
85
  }
63
86
 
87
+ /* call-seq: local_port -> Integer
88
+ *
89
+ * Returns the local port the socket is bound to.
90
+ *
91
+ * @return [Integer] the local port the socket is bound to, or 0 if it
92
+ * isn't connected
93
+ */
64
94
  static VALUE TcpSocket_local_port(VALUE self) {
65
95
  return UINT2NUM(sfTcpSocket_getLocalPort(Get_TcpSocket_Struct(self)));
66
96
  }
67
97
 
98
+ /* call-seq: remote_address -> IpAddress
99
+ *
100
+ * Returns the address of the remote peer.
101
+ *
102
+ * @return [IpAddress] the address of the remote peer, or +IpAddress::NONE+
103
+ * if not connected
104
+ */
68
105
  static VALUE TcpSocket_remote_address(VALUE self) {
69
106
  return ip_address_to_rb(sfTcpSocket_getRemoteAddress(Get_TcpSocket_Struct(self)));
70
107
  }
71
108
 
109
+ /* call-seq: remote_port -> Integer
110
+ *
111
+ * Returns the port of the remote peer.
112
+ *
113
+ * @return [Integer] the port of the remote peer, or 0 if not connected
114
+ */
72
115
  static VALUE TcpSocket_remote_port(VALUE self) {
73
116
  return UINT2NUM(sfTcpSocket_getRemotePort(Get_TcpSocket_Struct(self)));
74
117
  }
75
118
 
76
- static VALUE TcpSocket_connect(int argc, VALUE *argv, VALUE self) {
119
+ /* call-seq:
120
+ * connect(address, port, timeout = Time.zero) -> Symbol
121
+ *
122
+ * Connects to a remote peer, blocking (unless #blocking? is +false+) until
123
+ * connected or +timeout+ elapses.
124
+ *
125
+ * @return [Symbol] a SocketStatus name, +:done+ on success
126
+ */
127
+ static VALUE TcpSocket_connect(int argc, VALUE* argv, VALUE self) {
77
128
  VALUE rb_address, rb_port, rb_timeout;
78
129
  sfTime timeout = sfTime_Zero;
79
130
 
@@ -85,22 +136,45 @@ static VALUE TcpSocket_connect(int argc, VALUE *argv, VALUE self) {
85
136
 
86
137
  return ID2SYM(rb_intern(socket_status_name(sfTcpSocket_connect(
87
138
  Get_TcpSocket_Struct(self), ip_address_from_rb(rb_address, sfIpAddress_None),
88
- (unsigned short) NUM2INT(rb_port), timeout))));
139
+ (unsigned short)NUM2INT(rb_port), timeout))));
89
140
  }
90
141
 
142
+ /* call-seq: disconnect -> self
143
+ *
144
+ * Closes the connection.
145
+ *
146
+ * @return [self]
147
+ */
91
148
  static VALUE TcpSocket_disconnect(VALUE self) {
92
149
  sfTcpSocket_disconnect(Get_TcpSocket_Struct(self));
93
150
  return self;
94
151
  }
95
152
 
153
+ /* call-seq:
154
+ * send(data) -> Symbol
155
+ *
156
+ * Sends the full contents of +data+, blocking (unless #blocking? is
157
+ * +false+) until it is all sent. Prefer #send_partial for non-blocking
158
+ * sockets, since this can return +:not_ready+ having sent only part of
159
+ * the data with no way to know how much.
160
+ *
161
+ * @return [Symbol] a SocketStatus name, +:done+ on success
162
+ */
96
163
  static VALUE TcpSocket_send(VALUE self, VALUE rb_data) {
97
164
  StringValue(rb_data);
98
165
 
99
- return ID2SYM(rb_intern(socket_status_name(
100
- sfTcpSocket_send(Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data),
101
- (size_t) RSTRING_LEN(rb_data)))));
166
+ return ID2SYM(rb_intern(socket_status_name(sfTcpSocket_send(
167
+ Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data), (size_t)RSTRING_LEN(rb_data)))));
102
168
  }
103
169
 
170
+ /* call-seq:
171
+ * send_partial(data) -> [Integer, Symbol]
172
+ *
173
+ * Like #send, but may send only part of +data+ and reports how much.
174
+ *
175
+ * @return [Array(Integer, Symbol)] the number of bytes actually sent, and
176
+ * a SocketStatus name
177
+ */
104
178
  static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
105
179
  size_t sent = 0;
106
180
  sfSocketStatus status;
@@ -109,7 +183,7 @@ static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
109
183
  StringValue(rb_data);
110
184
 
111
185
  status = sfTcpSocket_sendPartial(Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data),
112
- (size_t) RSTRING_LEN(rb_data), &sent);
186
+ (size_t)RSTRING_LEN(rb_data), &sent);
113
187
 
114
188
  rb_result = rb_ary_new_capa(2);
115
189
  rb_ary_push(rb_result, SIZET2NUM(sent));
@@ -118,12 +192,19 @@ static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
118
192
  return rb_result;
119
193
  }
120
194
 
121
- /* Receive needs a maximum size up front because CSFML fills a caller buffer.
122
- Returns [data, status], where data is empty unless the status is :done. */
123
- static VALUE TcpSocket_receive(int argc, VALUE *argv, VALUE self) {
195
+ /* call-seq:
196
+ * receive(max_length = 1024) -> [String, Symbol]
197
+ *
198
+ * Receive needs a maximum size up front because CSFML fills a caller buffer.
199
+ * Returns [data, status], where data is empty unless the status is :done.
200
+ *
201
+ * @return [Array(String, Symbol)] the bytes received, and a SocketStatus name
202
+ * @raise [ArgumentError] if +max_length+ isn't positive
203
+ */
204
+ static VALUE TcpSocket_receive(int argc, VALUE* argv, VALUE self) {
124
205
  VALUE rb_max_length;
125
206
  long max_length = 1024;
126
- char *buffer;
207
+ char* buffer;
127
208
  size_t received = 0;
128
209
  sfSocketStatus status;
129
210
  VALUE rb_result;
@@ -138,12 +219,16 @@ static VALUE TcpSocket_receive(int argc, VALUE *argv, VALUE self) {
138
219
  rb_raise(rb_eArgError, "maximum length must be positive");
139
220
  }
140
221
 
141
- buffer = malloc((size_t) max_length);
222
+ buffer = malloc((size_t)max_length);
223
+
224
+ if (buffer == NULL) {
225
+ rb_raise(rb_eNoMemError, "failed to allocate receive buffer");
226
+ }
142
227
 
143
- status = sfTcpSocket_receive(Get_TcpSocket_Struct(self), buffer, (size_t) max_length, &received);
228
+ status = sfTcpSocket_receive(Get_TcpSocket_Struct(self), buffer, (size_t)max_length, &received);
144
229
 
145
230
  rb_result = rb_ary_new_capa(2);
146
- rb_ary_push(rb_result, rb_str_new(buffer, (long) received));
231
+ rb_ary_push(rb_result, rb_str_new(buffer, (long)received));
147
232
  rb_ary_push(rb_result, ID2SYM(rb_intern(socket_status_name(status))));
148
233
 
149
234
  free(buffer);
@@ -151,6 +236,14 @@ static VALUE TcpSocket_receive(int argc, VALUE *argv, VALUE self) {
151
236
  return rb_result;
152
237
  }
153
238
 
239
+ /* call-seq:
240
+ * send_packet(packet) -> Symbol
241
+ *
242
+ * Sends +packet+ over the connection.
243
+ *
244
+ * @return [Symbol] a SocketStatus name, +:done+ on success
245
+ * @raise [TypeError] if +packet+ is not an SFML::Packet
246
+ */
154
247
  static VALUE TcpSocket_send_packet(VALUE self, VALUE rb_packet) {
155
248
  if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
156
249
  rb_raise(rb_eTypeError, "expected an SFML::Packet");
@@ -160,6 +253,15 @@ static VALUE TcpSocket_send_packet(VALUE self, VALUE rb_packet) {
160
253
  sfTcpSocket_sendPacket(Get_TcpSocket_Struct(self), Get_Packet_Struct(rb_packet)))));
161
254
  }
162
255
 
256
+ /* call-seq:
257
+ * receive_packet(packet) -> Symbol
258
+ *
259
+ * Fills +packet+ (replacing its previous contents) with the next packet
260
+ * received.
261
+ *
262
+ * @return [Symbol] a SocketStatus name, +:done+ on success
263
+ * @raise [TypeError] if +packet+ is not an SFML::Packet
264
+ */
163
265
  static VALUE TcpSocket_receive_packet(VALUE self, VALUE rb_packet) {
164
266
  if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
165
267
  rb_raise(rb_eTypeError, "expected an SFML::Packet");
@@ -169,10 +271,16 @@ static VALUE TcpSocket_receive_packet(VALUE self, VALUE rb_packet) {
169
271
  sfTcpSocket_receivePacket(Get_TcpSocket_Struct(self), Get_Packet_Struct(rb_packet)))));
170
272
  }
171
273
 
172
- void Init_TcpSocket(VALUE rb_module) {
173
- rb_cTcpSocket = rb_define_class_under(rb_module, "TcpSocket", rb_cObject);
274
+ /* Document-class: SFML::TcpSocket
275
+ * A connection-oriented, reliable, byte-stream socket for TCP communication.
276
+ * Connect with #connect (or receive one already connected from
277
+ * TcpListener#accept), then send/receive raw bytes or Packet instances.
278
+ */
279
+ void Init_TcpSocket(VALUE rb_mSFML) {
280
+ rb_cTcpSocket = rb_define_class_under(rb_mSFML, "TcpSocket", rb_cObject);
281
+ rb_define_alloc_func(rb_cTcpSocket, TcpSocket_alloc);
174
282
 
175
- rb_define_singleton_method(rb_cTcpSocket, "new", TcpSocket_new, 0);
283
+ rb_define_method(rb_cTcpSocket, "initialize", TcpSocket_initialize, 0);
176
284
 
177
285
  rb_define_method(rb_cTcpSocket, "blocking?", TcpSocket_blocking, 0);
178
286
  rb_define_method(rb_cTcpSocket, "blocking=", TcpSocket_set_blocking, 1);
@@ -192,8 +300,8 @@ VALUE Get_Klass_TcpSocket(void) {
192
300
  return rb_cTcpSocket;
193
301
  }
194
302
 
195
- void *Get_TcpSocket_Struct(VALUE self) {
196
- TcpSocket *ptr;
303
+ void* Get_TcpSocket_Struct(VALUE self) {
304
+ TcpSocket* ptr;
197
305
  TypedData_Get_Struct(self, TcpSocket, &TcpSocket_data_type, ptr);
198
306
  return ptr->handle;
199
307
  }