rufus-lua 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,14 @@
2
2
  = rufus-lua CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-lua - 1.0.0 not yet released
6
+
7
+ - automatically creates lib table when defined Ruby function (callback)
8
+ - implemented #[]=, #objlen and #size for table
9
+ - fixed bug when pushing floats on the stack (float --> double)
10
+ - added State#function for defining Ruby functions (callbacks) available via Lua
11
+
12
+
5
13
  == rufus-lua - 0.1.0 released 2009/03/16
6
14
 
7
15
  - initial release
data/LICENSE.txt CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ Copyright (c) 2009, John Mettraux, Alain Hoang.
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
data/README.txt CHANGED
@@ -3,15 +3,14 @@
3
3
 
4
4
  Lua embedded in Ruby, via Ruby FFI
5
5
 
6
- Tested with Ruby 1.8.6, Ruby 1.9.1p0 and JRuby 1.1.6
6
+ Tested with
7
+ ruby 1.8.6, ruby 1.9.1p0, jruby 1.2.0
8
+ jruby 1.1.6 has an issue with errors raised inside of Ruby functions (callbacks)
7
9
 
8
10
 
9
11
  == Lua
10
12
 
11
- from
12
-
13
- http://www.lua.org/
14
- http://www.lua.org/about.html
13
+ http://www.lua.org/about.html says :
15
14
 
16
15
  """
17
16
  Lua is a powerful, fast, lightweight, embeddable scripting language.
@@ -19,6 +18,8 @@ Lua is a powerful, fast, lightweight, embeddable scripting language.
19
18
  Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode for a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.
20
19
  """
21
20
 
21
+ http://www.lua.org/
22
+
22
23
 
23
24
  == other Ruby and Lua bridges / connectors
24
25
 
@@ -46,18 +47,83 @@ then
46
47
 
47
48
  s.close
48
49
 
49
- rufus-lua's rdoc is at http://rufus.rubyforge.org/rufus-lua/
50
+
51
+ === binding Ruby code as Lua functions
52
+
53
+ require 'rubygems'
54
+ require 'rufus/lua'
55
+
56
+ s = Rufus::Lua::State.new
57
+
58
+ s.function 'key_up' do |table|
59
+ table.inject({}) do |h, (k, v)|
60
+ h[k.to_s.upcase] = v
61
+ end
62
+ end
63
+
64
+ p s.eval(%{
65
+ local table = { CoW = 2, pigs = 3, DUCKS = 'none' }
66
+ return key_up(table) -- calling Ruby from Lua...
67
+ }).to_h
68
+ # => { 'COW' => 2.0, 'DUCKS => 'none', 'PIGS' => 3.0 }
69
+
70
+ s.close
71
+
72
+
73
+ It's OK to bind a function inside of a table (library) :
74
+
75
+ require 'rubygems'
76
+ require 'rufus/lua'
77
+
78
+ s = Rufus::Lua::State.new
79
+
80
+ s.eval("rubies = {}")
81
+ s.function 'add' do |x, y|
82
+ x + y
83
+ end
84
+
85
+ s.eval("rubies.add(1, 2)")
86
+ # => 3.0
87
+
88
+ s.close
89
+
90
+
91
+ You can omit the table definition (only 1 level allowed here though) :
92
+
93
+ require 'rubygems'
94
+ require 'rufus/lua'
95
+
96
+ s = Rufus::Lua::State.new
97
+
98
+ s.function 'rubies.add' do |x, y|
99
+ x + y
100
+ end
101
+
102
+ s.eval("rubies.add(1, 2)")
103
+ # => 3.0
104
+
105
+ s.close
106
+
107
+
108
+
109
+ The specs contain more examples :
110
+
111
+ http://github.com/jmettraux/rufus-lua/tree/master/spec/
112
+
113
+ rufus-lua's rdoc is at :
114
+
115
+ http://rufus.rubyforge.org/rufus-lua/
50
116
 
51
117
 
52
118
  == compiling liblua.dylib
53
119
 
54
120
  original instructions by Adrian Perez at :
55
121
 
56
- http://lua-users.org/lists/lua-l/2006-09/msg00894.html
122
+ http://lua-users.org/lists/lua-l/2006-09/msg00894.html
57
123
 
58
124
  get the source at
59
125
 
60
- http://www.lua.org/ftp/lua-5.1.4.tar.gz
126
+ http://www.lua.org/ftp/lua-5.1.4.tar.gz
61
127
 
62
128
  then
63
129
 
@@ -83,6 +149,12 @@ The following gems are needed to run the specs
83
149
  install bacon
84
150
 
85
151
 
152
+ == tested with
153
+
154
+ ruby 1.8.6, ruby 1.9.1p0, jruby 1.2.0
155
+ jruby 1.1.6 has an issue with errors raised inside of Ruby functions (callbacks)
156
+
157
+
86
158
  == dependencies
87
159
 
88
160
  the ruby gem 'ffi'
@@ -116,8 +188,9 @@ http://github.com/jmettraux/rufus-lua
116
188
 
117
189
  many thanks to the authors of Ruby FFI, and of Lua
118
190
 
119
- http://kenai.com/projects/ruby-ffi/
120
- http://lua.org/
191
+ http://kenai.com/projects/ruby-ffi/
192
+
193
+ http://lua.org/
121
194
 
122
195
 
123
196
  == authors
@@ -137,5 +210,5 @@ MIT
137
210
 
138
211
  Lua itself is licensed under the MIT license as well :
139
212
 
140
- http://www.lua.org/license.html
213
+ http://www.lua.org/license.html
141
214
 
data/TODO.txt CHANGED
@@ -12,8 +12,12 @@
12
12
  [o] fib.lua, use local, bench ! (2 times faster almost)
13
13
 
14
14
  [ ] add GC control methods (Alain)
15
- [ ] Add method to disable GC
16
- [ ] Add method to enable GC
15
+ [X] Add method to disable GC
16
+ [X] Add method to enable GC
17
17
  [ ] Look at parameters in Lua GC that can be tweaked
18
18
  [ ] Add method to tune GC parameters
19
+ [ ] Test whether GC is truly independent for each state
20
+
21
+ [x] ruby callbacks (functions)
22
+ [ ] ability to bind ruby functions (callbacks) inside of tables (modules)
19
23
 
data/lib/rufus/lua.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2009, John Mettraux, Alain Hoang.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
data/lib/rufus/lua/lib.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2009, John Mettraux, Alain Hoang.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -39,17 +39,20 @@ module Lua
39
39
  paths = Array(ENV['LUA_LIB'] || %w{
40
40
  /opt/local/lib/liblua.dylib
41
41
  /usr/local/lib/liblua.dylib
42
+ /opt/local/lib/liblua.so
42
43
  /usr/local/lib/liblua.so
43
44
  })
44
45
 
45
- path = paths.find { |path| File.exist?(path) }
46
+ begin
46
47
 
47
- raise(
48
- "didn't find the lua dylib on your system, " +
49
- "see http://rufus.rubyforge.org/rufus-lua/ to learn how to get it"
50
- ) unless path
48
+ ffi_lib(*paths)
51
49
 
52
- ffi_lib(path)
50
+ rescue LoadError => le
51
+ raise(
52
+ "didn't find the lua dylib on your system, " +
53
+ "see http://rufus.rubyforge.org/rufus-lua/ to learn how to get it"
54
+ )
55
+ end
53
56
 
54
57
  #
55
58
  # attach functions
@@ -64,7 +67,7 @@ module Lua
64
67
  #attach_function :lua_resume, [ :pointer, :int ], :int
65
68
 
66
69
  attach_function :lua_toboolean, [ :pointer, :int ], :int
67
- attach_function :lua_tonumber, [ :pointer, :int ], :float
70
+ attach_function :lua_tonumber, [ :pointer, :int ], :double
68
71
  attach_function :lua_tolstring, [ :pointer, :int, :pointer ], :string
69
72
 
70
73
  attach_function :lua_type, [ :pointer, :int ], :int
@@ -77,12 +80,16 @@ module Lua
77
80
  attach_function :lua_getfield, [ :pointer, :int, :string ], :pointer
78
81
  attach_function :lua_gettable, [ :pointer, :int ], :void
79
82
 
83
+ attach_function :lua_createtable, [ :pointer, :int, :int ], :void
84
+ #attach_function :lua_newtable, [ :pointer ], :void
85
+ attach_function :lua_settable, [ :pointer, :int ], :void
86
+
80
87
  attach_function :lua_next, [ :pointer, :int ], :int
81
88
 
82
89
  attach_function :lua_pushnil, [ :pointer ], :pointer
83
90
  attach_function :lua_pushboolean, [ :pointer, :int ], :pointer
84
91
  attach_function :lua_pushinteger, [ :pointer, :int ], :pointer
85
- attach_function :lua_pushnumber, [ :pointer, :float ], :pointer
92
+ attach_function :lua_pushnumber, [ :pointer, :double ], :pointer
86
93
  attach_function :lua_pushstring, [ :pointer, :string ], :pointer
87
94
 
88
95
  attach_function :lua_rawgeti, [ :pointer, :int, :int ], :void
@@ -91,6 +98,12 @@ module Lua
91
98
  attach_function :luaL_loadbuffer, [ :pointer, :string, :int, :string ], :int
92
99
  attach_function :luaL_ref, [ :pointer, :int ], :int
93
100
  attach_function :luaL_unref, [ :pointer, :int, :int ], :void
101
+
102
+ attach_function :lua_gc, [ :pointer, :int, :int ], :int
103
+
104
+ callback :cfunction, [ :pointer ], :int
105
+ attach_function :lua_pushcclosure, [ :pointer, :cfunction, :int ], :void
106
+ attach_function :lua_setfield, [ :pointer, :int, :string ], :void
94
107
  end
95
108
  end
96
109
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2009, John Mettraux, Alain Hoang.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -39,8 +39,10 @@ module Rufus::Lua
39
39
  attr_reader :ref
40
40
 
41
41
  def initialize (pointer)
42
+
42
43
  @pointer = pointer
43
44
  @ref = Lib.luaL_ref(@pointer, LUA_REGISTRYINDEX)
45
+ # this pops the object out of the stack !
44
46
  end
45
47
 
46
48
  #
@@ -190,13 +192,43 @@ module Rufus::Lua
190
192
  stack_pop
191
193
  end
192
194
 
193
- #--
194
- # TODO : implement (maybe)
195
195
  #
196
- #def []= (k, v)
197
- # raise 'not yet !'
198
- #end
199
- #++
196
+ # Sets a value in the table
197
+ #
198
+ # TODO : have something for adding in the array part...
199
+ #
200
+ def []= (k, v)
201
+
202
+ load_onto_stack
203
+
204
+ stack_push(k)
205
+ stack_push(v)
206
+ Lib.lua_settable(@pointer, -3)
207
+
208
+ v
209
+ end
210
+
211
+ #
212
+ # Returns the size of the table, corresponds to the Lua '#' operator.
213
+ #
214
+ # Will thus return 0 if the table doesn't hold any value in its
215
+ # 'array' part.
216
+ #
217
+ def objlen
218
+
219
+ load_onto_stack
220
+ Lib.lua_objlen(@pointer, -1)
221
+ end
222
+
223
+ #
224
+ # Returns the real size of the table (number of entries + number of elements
225
+ # in array side)
226
+ #
227
+ def size
228
+
229
+ self.to_h.size
230
+ end
231
+ alias :length :size
200
232
 
201
233
  #
202
234
  # Returns a Ruby Hash instance representing this Lua table.
@@ -214,7 +246,10 @@ module Rufus::Lua
214
246
  while Lib.lua_next(@pointer, table_pos) != 0 do
215
247
 
216
248
  value = stack_fetch(-1)
249
+ value.load_onto_stack if value.is_a?(Ref)
250
+
217
251
  key = stack_fetch(-2)
252
+ key.load_onto_stack if key.is_a?(Ref)
218
253
 
219
254
  stack_unstack # leave key on top
220
255
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2009, John Mettraux, Alain Hoang.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,8 @@
25
25
 
26
26
  module Rufus::Lua
27
27
 
28
+ VERSION = '1.0.0'
29
+
28
30
  #
29
31
  # An error class for this gem/library.
30
32
  #
@@ -46,6 +48,16 @@ module Rufus::Lua
46
48
  LUA_NOREF = -2
47
49
  LUA_REFNIL = -1
48
50
 
51
+ # Lua GC constants
52
+ LUA_GCSTOP = 0
53
+ LUA_GCRESTART = 1
54
+ LUA_GCCOLLECT = 2
55
+ LUA_GCCOUNT = 3
56
+ LUA_GCCOUNTB = 4
57
+ LUA_GCSTEP = 5
58
+ LUA_GCSETPAUSE = 6
59
+ LUA_GCSETSTEPMUL = 7
60
+
49
61
  TNONE = -1
50
62
  TNIL = 0
51
63
  TBOOLEAN = 1
@@ -57,6 +69,8 @@ module Rufus::Lua
57
69
  TUSERDATA = 7
58
70
  TTHREAD = 8
59
71
 
72
+ SIMPLE_TYPES = [ TNIL, TBOOLEAN, TNUMBER, TSTRING ]
73
+
60
74
  LUA_MULTRET = -1
61
75
 
62
76
  protected
@@ -99,11 +113,25 @@ module Rufus::Lua
99
113
  # warning : don't touch at stack[0]
100
114
 
101
115
  s = (1..stack_top).inject([]) { |a, i|
116
+
102
117
  type, tname = stack_type_at(i)
103
- a << "#{i} : #{tname} (#{type})"
118
+
119
+ val = if type == TSTRING
120
+ "\"#{stack_fetch(i)}\""
121
+ elsif SIMPLE_TYPES.include?(type)
122
+ stack_fetch(i).to_s
123
+ elsif type == TTABLE
124
+ "(# is #{Lib.lua_objlen(@pointer, i)})"
125
+ else
126
+ ''
127
+ end
128
+
129
+ a << "#{i} : #{tname} (#{type}) #{val}"
104
130
  a
105
131
  }.reverse.join("\n")
132
+
106
133
  s += "\n" if s.length > 0
134
+
107
135
  s
108
136
  end
109
137
 
@@ -180,6 +208,11 @@ module Rufus::Lua
180
208
 
181
209
  new_top = stack_top - 1
182
210
  new_top = 0 if new_top < 0
211
+ #
212
+ # there are no safeguard in Lua, setting top to -2 work well
213
+ # when the stack is crowed, but it has bad side effects when the
214
+ # stack is empty... Now safeguarding by ourselves.
215
+
183
216
  Lib.lua_settop(@pointer, new_top)
184
217
  end
185
218
 
@@ -200,8 +233,8 @@ module Rufus::Lua
200
233
 
201
234
  when String then Lib.lua_pushstring(@pointer, o)
202
235
 
203
- #when Hash then ...
204
- #when Array then ...
236
+ when Hash then stack_push_hash(o)
237
+ when Array then stack_push_array(o)
205
238
 
206
239
  else raise(
207
240
  ArgumentError.new(
@@ -209,6 +242,36 @@ module Rufus::Lua
209
242
  end
210
243
  end
211
244
 
245
+ #
246
+ # Pushes a hash on top of the Lua stack.
247
+ #
248
+ def stack_push_hash (h)
249
+
250
+ Lib.lua_createtable(@pointer, 0, h.size)
251
+ # since we already know the size of the table...
252
+
253
+ h.each do |k, v|
254
+ stack_push(k)
255
+ stack_push(v)
256
+ Lib.lua_settable(@pointer, -3)
257
+ end
258
+ end
259
+
260
+ #
261
+ # Pushes an array on top of the Lua stack.
262
+ #
263
+ def stack_push_array (a)
264
+
265
+ Lib.lua_createtable(@pointer, a.size, 0)
266
+ # since we already know the size of the table...
267
+
268
+ a.each_with_index do |e, i|
269
+ stack_push(i)
270
+ stack_push(e)
271
+ Lib.lua_settable(@pointer, -3)
272
+ end
273
+ end
274
+
212
275
  #
213
276
  # Loads a Lua global value on top of the stack
214
277
  #
@@ -352,6 +415,85 @@ module Rufus::Lua
352
415
  k.index('.') ? self.eval("return #{k}") : get_global(k)
353
416
  end
354
417
 
418
+ #
419
+ # Binds a Ruby function (callback) in the top environment of Lua
420
+ #
421
+ # require 'rubygems'
422
+ # require 'rufus/lua'
423
+ #
424
+ # s = Rufus::Lua::State.new
425
+ #
426
+ # s.function 'key_up' do |table|
427
+ # table.inject({}) do |h, (k, v)|
428
+ # h[k.to_s.upcase] = v
429
+ # end
430
+ # end
431
+ #
432
+ # p s.eval(%{
433
+ # local table = {}
434
+ # table['CoW'] = 2
435
+ # table['pigs'] = 3
436
+ # table['DUCKS'] = 'none'
437
+ # return key_up(table)
438
+ # }).to_h
439
+ # # => { 'COW' => 2.0, 'DUCKS => 'none', 'PIGS' => 3.0 }
440
+ #
441
+ # s.close
442
+ #
443
+ def function (name, &block)
444
+
445
+ raise 'please pass a block for the body of the function' unless block
446
+
447
+ callback = Proc.new do |state|
448
+
449
+ args = block.arity > 0 ?
450
+ (1..block.arity).collect { |i| stack_pop } :
451
+ []
452
+
453
+ result = block.call(*args)
454
+
455
+ if result.is_a?(Hash)
456
+ stack_push(result)
457
+ 1
458
+ else
459
+ result = Array(result)
460
+ result.each { |e| stack_push(e) }
461
+ result.size
462
+ end
463
+ end
464
+
465
+ name = name.to_s
466
+
467
+ name, index = if ri = name.rindex('.')
468
+ #
469
+ # bind in the given table
470
+
471
+ table_name = name[0..ri-1]
472
+
473
+ t = self.eval("return #{table_name}") rescue nil
474
+
475
+ raise ArgumentError.new(
476
+ "won't create automatically nested tables"
477
+ ) if (not t) and table_name.index('.')
478
+
479
+ t = self.eval("#{table_name} = {}; return #{table_name}") \
480
+ unless t
481
+
482
+ t.send(:load_onto_stack)
483
+
484
+ [ name[ri+1..-1], -2 ]
485
+
486
+ else
487
+ #
488
+ # bind function at the global level
489
+
490
+ [ name, LUA_GLOBALSINDEX ]
491
+ end
492
+
493
+ Lib.lua_pushcclosure(@pointer, callback, 0)
494
+ Lib.lua_setfield(@pointer, index, name)
495
+ end
496
+
355
497
  #
356
498
  # Closes the state.
357
499
  #
@@ -360,7 +502,45 @@ module Rufus::Lua
360
502
  #
361
503
  def close
362
504
 
505
+ raise "State already closed" unless @pointer
363
506
  Lib.lua_close(@pointer)
507
+ @pointer = nil
508
+ end
509
+
510
+ #
511
+ # Returns current amount of memory in KB in use by Lua
512
+ #
513
+ def gc_count
514
+
515
+ raise "State got closed, cannot proceed" unless @pointer
516
+ Lib.lua_gc(@pointer, LUA_GCCOUNT, 0)
517
+ end
518
+
519
+ #
520
+ # Runs garbage collection
521
+ #
522
+ def gc_collect!
523
+
524
+ raise "State got closed, cannot proceed" unless @pointer
525
+ Lib.lua_gc(@pointer, LUA_GCCOLLECT, 0)
526
+ end
527
+
528
+ #
529
+ # Stop garbage collection for this state
530
+ #
531
+ def gc_stop
532
+
533
+ raise "State got closed, cannot proceed" unless @pointer
534
+ Lib.lua_gc(@pointer, LUA_GCSTOP, 0)
535
+ end
536
+
537
+ #
538
+ # Restart garbage collection for this state
539
+ #
540
+ def gc_resume
541
+
542
+ raise "State got closed, cannot proceed" unless @pointer
543
+ Lib.lua_gc(@pointer, LUA_GCRESTART, 0)
364
544
  end
365
545
  end
366
546
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2009, John Mettraux, Alain Hoang.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
data/t.txt ADDED
@@ -0,0 +1,24 @@
1
+ $ ruby19 test/bm_fiber.rb
2
+ user system total real
3
+ ruby 0.050000 0.010000 0.060000 ( 0.054605)
4
+ lua via ruby 0.180000 0.000000 0.180000 ( 0.189010)
5
+ lua 0.010000 0.000000 0.010000 ( 0.005543)
6
+
7
+ $ ruby19 test/bm_fiber.rb
8
+ user system total real
9
+ ruby 0.050000 0.000000 0.050000 ( 0.051531)
10
+ lua via ruby 0.180000 0.010000 0.190000 ( 0.194944)
11
+ lua 0.010000 0.000000 0.010000 ( 0.006325)
12
+
13
+ $ ruby19 test/bm_fiber.rb
14
+ user system total real
15
+ ruby 0.050000 0.010000 0.060000 ( 0.052032)
16
+ lua via ruby 0.180000 0.000000 0.180000 ( 0.195411)
17
+ lua 0.010000 0.000000 0.010000 ( 0.006394)
18
+
19
+ $ ruby19 test/bm_fiber.rb
20
+ user system total real
21
+ ruby 0.050000 0.010000 0.060000 ( 0.054892)
22
+ lua via ruby 0.180000 0.000000 0.180000 ( 0.267880)
23
+ lua 0.000000 0.000000 0.000000 ( 0.005865)
24
+
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-lua
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
+ - Alain Hoang
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2009-03-16 00:00:00 +09:00
13
+ date: 2009-03-27 00:00:00 +09:00
13
14
  default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
@@ -44,6 +45,7 @@ files:
44
45
  - CREDITS.txt
45
46
  - LICENSE.txt
46
47
  - README.txt
48
+ - t.txt
47
49
  - TODO.txt
48
50
  has_rdoc: true
49
51
  homepage: http://rufus.rubyforge.org/