├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── docs ├── content │ ├── amemmgt.js │ ├── api.js │ ├── cursors.js │ ├── cycles.js │ ├── escmsgs.js │ ├── example_1.js │ ├── example_2.js │ ├── example_3.js │ ├── examples.js │ ├── installation.js │ ├── introduction.js │ ├── longprnms.js │ ├── mapval.js │ ├── restrict.js │ ├── rm_.js │ ├── rm__.js │ ├── rm__a.js │ ├── rm__aa.js │ ├── rm__d.js │ ├── rm__i.js │ ├── rm__n.js │ ├── rm__p.js │ ├── rm__s.js │ ├── rm__sa.js │ ├── rm__t.js │ ├── rm__x.js │ ├── rm__xp.js │ ├── rm__z.js │ ├── rm_a.js │ ├── rm_a1_.js │ ├── rm_a1__.js │ ├── rm_a2_.js │ ├── rm_a2__.js │ ├── rm_a3_.js │ ├── rm_a3__.js │ ├── rm_a_.js │ ├── rm_a__.js │ ├── rm_aa.js │ ├── rm_aap.js │ ├── rm_add_event_handler.js │ ├── rm_ap.js │ ├── rm_ceq.js │ ├── rm_cge.js │ ├── rm_cgt.js │ ├── rm_cle.js │ ├── rm_clt.js │ ├── rm_cmp.js │ ├── rm_cpy.js │ ├── rm_cpyd.js │ ├── rm_cur.js │ ├── rm_d.js │ ├── rm_d_.js │ ├── rm_d__.js │ ├── rm_dis.js │ ├── rm_fed.js │ ├── rm_fedr.js │ ├── rm_gav.js │ ├── rm_gcf.js │ ├── rm_get.js │ ├── rm_gik.js │ ├── rm_hit.js │ ├── rm_hks.js │ ├── rm_hky.js │ ├── rm_hsn.js │ ├── rm_hsp.js │ ├── rm_i.js │ ├── rm_i1.js │ ├── rm_i1_.js │ ├── rm_i1__.js │ ├── rm_i2.js │ ├── rm_i2_.js │ ├── rm_i2__.js │ ├── rm_i_.js │ ├── rm_i__.js │ ├── rm_inm.js │ ├── rm_ins.js │ ├── rm_ins1.js │ ├── rm_insc.js │ ├── rm_insc1.js │ ├── rm_inscm.js │ ├── rm_insm.js │ ├── rm_insx.js │ ├── rm_insx1.js │ ├── rm_insxm.js │ ├── rm_isa.js │ ├── rm_isaa.js │ ├── rm_isd.js │ ├── rm_isi.js │ ├── rm_isi1.js │ ├── rm_isi2.js │ ├── rm_ism.js │ ├── rm_ismm.js │ ├── rm_isn.js │ ├── rm_isp.js │ ├── rm_isp1.js │ ├── rm_isp2.js │ ├── rm_isp3.js │ ├── rm_iss.js │ ├── rm_issa.js │ ├── rm_ist.js │ ├── rm_isv.js │ ├── rm_isx.js │ ├── rm_isxp.js │ ├── rm_isz.js │ ├── rm_itm.js │ ├── rm_key.js │ ├── rm_m.js │ ├── rm_mm.js │ ├── rm_mmi.js │ ├── rm_mmm.js │ ├── rm_n.js │ ├── rm_n_.js │ ├── rm_n__.js │ ├── rm_nit.js │ ├── rm_num.js │ ├── rm_p.js │ ├── rm_p1.js │ ├── rm_p1_.js │ ├── rm_p1__.js │ ├── rm_p2.js │ ├── rm_p2_.js │ ├── rm_p2__.js │ ├── rm_p3.js │ ├── rm_p3_.js │ ├── rm_p3__.js │ ├── rm_p_.js │ ├── rm_p__.js │ ├── rm_rdn.js │ ├── rm_rdp.js │ ├── rm_remove_event_handler.js │ ├── rm_rmv.js │ ├── rm_rmva.js │ ├── rm_s.js │ ├── rm_s1_.js │ ├── rm_s1__.js │ ├── rm_s2_.js │ ├── rm_s2__.js │ ├── rm_s3_.js │ ├── rm_s3__.js │ ├── rm_s_.js │ ├── rm_s__.js │ ├── rm_sa.js │ ├── rm_sab.js │ ├── rm_sav.js │ ├── rm_sb.js │ ├── rm_scf.js │ ├── rm_sgt.js │ ├── rm_sgtp.js │ ├── rm_sll.js │ ├── rm_slln.js │ ├── rm_t.js │ ├── rm_t_.js │ ├── rm_t__.js │ ├── rm_usrd.js │ ├── rm_v.js │ ├── rm_x.js │ ├── rm_x_.js │ ├── rm_x__.js │ ├── rm_xp.js │ ├── rm_xp_.js │ ├── rm_xp__.js │ ├── rm_z.js │ ├── rm_z_.js │ ├── rm_z__.js │ ├── sortord.js │ ├── threads.js │ ├── usage.js │ └── vectors.js ├── css │ ├── main.css │ └── normalize.min.css └── index.html └── src ├── BUILD.sh ├── LICENSE ├── RPGMAP.BND ├── RPGMAP.RPGLE ├── RPGMAPCVA.t.RPGLE ├── RPGMAPCVAH.RPGLE ├── RPGMAPGDEF.t.RPGLE ├── RPGMAPGMF.t.RPGLE ├── RPGMAPGMFH.RPGLE ├── RPGMAPI001.RPGLE ├── RPGMAPI002.RPGLE ├── RPGMAPI003.RPGLE ├── RPGMAPI051.RPGLE ├── RPGMAPI052.RPGLE ├── RPGMAPI053.RPGLE ├── RPGMAPI054.RPGLE ├── RPGMAPI055.RPGLE ├── RPGMAPI056.RPGLE ├── RPGMAPI057.RPGLE ├── RPGMAPI058.RPGLE ├── RPGMAPI059.RPGLE ├── RPGMAPI060.RPGLE ├── RPGMAPI061.RPGLE ├── RPGMAPI062.RPGLE ├── RPGMAPI063.RPGLE ├── RPGMAPI064.RPGLE ├── RPGMAPI101.RPGLE ├── RPGMAPI102.RPGLE ├── RPGMAPI103.RPGLE ├── RPGMAPI104.RPGLE ├── RPGMAPI151.RPGLE ├── RPGMAPI152.RPGLE ├── RPGMAPI153.RPGLE ├── RPGMAPI154.RPGLE ├── RPGMAPI155.RPGLE ├── RPGMAPI156.RPGLE ├── RPGMAPI157.RPGLE ├── RPGMAPI158.RPGLE ├── RPGMAPI159.RPGLE ├── RPGMAPI160.RPGLE ├── RPGMAPI161.RPGLE ├── RPGMAPI162.RPGLE ├── RPGMAPI163.RPGLE ├── RPGMAPI164.RPGLE ├── RPGMAPLPN.t.RPGLE ├── RPGMAPLPNH.RPGLE ├── RPGMAPMAIN.t.RPGLE ├── RPGMAPRBTC.C ├── RPGMAPRBTC.H ├── RPGMAPRBTC.RPGLE ├── RPGMAPSYS.RPGLE ├── RPGMAPSYSH.RPGLE ├── RPGMAPT000.t.RPGLE ├── RPGMAPT001.t.RPGLE ├── RPGMAPT002.t.RPGLE ├── RPGMAPT003.t.RPGLE ├── RPGMAPVAL.t.RPGLE └── RPGMAPVALH.RPGLE /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.bin binary 3 | *.zip binary 4 | *.png binary 5 | *.jpg binary 6 | *.jpeg binary 7 | *.RPG linguist-language=RPG 8 | *.RPGLE linguist-language=RPG 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | .DS_Store 3 | .vscode 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2019 John Erps 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## RpgMap v1.2.1 2 | 3 | #### RpgMap implements a versatile in-memory ordered key/value store, like a Java TreeMap or a Python dict, for use with the RPG programming language 4 | 5 | *** 6 | 7 | ### [Docs](https://johnerps.com/RpgMap/docs/index.html) 8 | 9 | *** 10 | 11 | ### License 12 | 13 | RpgMap is [MIT Licensed](LICENSE.md). You may use, distribute and copy it under the license terms. 14 | 15 | File RPGMAPRBTC.C (RedBlackTree implementation) was originally developed by Emin Martinian. 16 | 17 | ### Changes 18 | 19 | * v1.2.1 (march 2019) 20 | 21 | * Dir Source renamed to src. Misc. changes. 22 | 23 | * v1.2.0 (july 2018) 24 | 25 | * New procedures: 26 | 27 | * Fixed bug "obj already contained" in `rm_ins?m`. 28 | 29 | * RPGMAP signature is now "V1" and only changes when the major version number is changed. 30 | 31 | * `rm_??__` to immediately dispose an RpgMap value after unwrapping. 32 | 33 | * `rm_inm (rm_in_map)` to test whether a map or value is (contained) in a map. 34 | 35 | * `rm_mmm (rm_make_map_manually_disposed)` to make a map manually disposed. 36 | 37 | * `rm_mmi (rm_make_map_immutable)` to make a map immutable. 38 | 39 | * v1.1.0 (dec 2017) 40 | 41 | * Start with semver versioning scheme. 42 | 43 | * V2017.3 (sept 2017) 44 | 45 | * Fixed bug which caused procedure `rm_isv` to return *on for a normal map. 46 | 47 | * Maps can have event handlers which listen to "insert" and "remove" events. 48 | 49 | * Values and maps can now have associated "user data", which is an arbitrary integer value between 1 and 65.000. 50 | 51 | * Procedure `rm_sav (rm_set_attr_value)` now accepts up to 100 attribute name/values. 52 | 53 | * Parameter `pos` is now optional for procedures `rm_slln` and `rm_sgtp`. 54 | 55 | * New procedures: 56 | 57 | * `rm_usrd (rm_user_data)` (return user data) returns the user data associated with a map or value. 58 | 59 | * `rm_ismm` (is manually disposed map?) to test whether an object is a manually disposed map. 60 | 61 | * `rm_add_event_handler` (add event handler) to add an event handler to a map. 62 | 63 | * `rm_remove_event_handler` (remove event handler) to remove an event handler from a map. 64 | 65 | * V2017.2 (aug 2017) 66 | 67 | * Many procedures now have a long procedure name besides the short name. The long name 68 | can optionally be used when a more descriptive name is needed. For example `rm_insc` can also be called as `rm_insert_cond`. 69 | 70 | * New procedures: 71 | 72 | * `rm_hit (rm_has_item)` (has item?) to test whether a map has an item equal to a given item. 73 | 74 | * `rm_nit (rm_num_items)` (number of items) which returns the number of items equal to a given item. 75 | 76 | * `rm_gik (rm_get_item_key)` (get item key) which returns the key of the first or last item equal to a given item. 77 | 78 | * V2017.1 (jul 2017) 79 | 80 | * Initial 81 | -------------------------------------------------------------------------------- /docs/content/amemmgt.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 6 | Maps and values must be disposed at some time to free the used memory and not cause memory leaks. \ 7 | To help with that RpgMap implements some simple rules that govern automatic disposal of maps and values.\ 8 |
\ 9 |\
10 | Procedure rm_dis
is used to explicitly dispose values, maps and cursors.\
11 |
\
13 | Every data type has a rm_??__
procedure (two trailing underscores) to dispose a value immediately \
14 | after unwrapping.\
15 |
\
17 | ●●● When a value is inserted in a map as key or item and the map is disposed or the key/item pair is removed \
18 | from the map then the value is disposed.
\
19 |
\
20 | ●●● When a value is used as an argument, e.g. as a key when calling rm_get
, \
21 | and the value has not been inserted into a map then the value is immediately disposed after being used.
\
22 |
\ 23 | Because a value is automatically disposed it can not be inserted into more than one map.\ 24 |
\ 25 |\
26 | Maps come in mainly two flavors: automatically (rm_m
) or manually (rm_mm
) disposed.\
27 |
\
29 | ●●● Automatically disposed maps are governed by the same memory management rules as values.
\
30 |
\ 32 | I.e. they\'re disposed when the containing map is disposed or when an automatically disposed map is removed \ 33 | from the map, or when it has been used as an argument and is not contained in a map.\ 34 |
\ 35 |\ 36 | An automatically disposed map can not be inserted into more than one map.\ 37 |
\ 38 |\ 39 | The documentation of procedures accepting automatically disposed maps are values as arguments clearly state whether \ 40 | any arguments will be disposed.\ 41 |
\ 42 |\
43 | A manually disposed map must always be explicitly disposed with rm_dis
. \
44 | But unlike an automatically disposed map a manually disposed map can be inserted into more than one map.\
45 |
\
47 | A value or an automatically disposed map that has been inserted into a map can not be explicitly disposed \
48 | with rm_dis
, or with one of the rm_??__
procedures.\
49 |
\
51 | When a map is copied (rm_cpy
) the copy contains a copy of the \
52 | values and automatically disposed maps in the original. Manually disposed maps are only copied \
53 | when a deep copy is made (rm_cpyd
).\
54 |
\
56 | Similar to copying a map, when keys/items are inserted from a map (e.g. rm_insm
) then \
57 | only manually disposed maps are directly inserted, while a copy of the values and automatically disposed \
58 | maps is inserted.\
59 |
\
61 | An automatically disposed map (not a vector) can be made manually disposed with rm_mmm
, \
62 | but not vice versa.\
63 |
\ 6 | The following is the list of all procedures that make up the API of RpgMap. \ 7 | For every procedure the signature is shown which specifies the result type \ 8 | and the parameters. If a procedure has a short and long name then the long name \ 9 | is shown just below the short name.\ 10 |
\ 11 | \ 12 | '); 13 | -------------------------------------------------------------------------------- /docs/content/cursors.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |\
6 | Cursors are used to iterate through the key/item pairs of a map. A cursor maintains a current position \
7 | within the key/item pairs of a map. A cursor must first be created with rm_cur
.\
8 |
\
10 | A cursor\'s position can be set with set-lower-limit, rm_sll
, or \
11 | set-greater-than, rm_sgt
. Procedures rm_rdn
\
12 | and rm_rdp
must be used to read the next or previous key/item pair. \
13 | Procedures rm_key
and rm_itm
\
14 | must be used to read the current key and item.\
15 |
\
17 | A cursor must be disposed with rm_dis
, or it is automatically \
18 | disposed when it\'s associated map is disposed.\
19 |
\ 21 | See example 2 and example 3.\ 22 |
\ 23 |\
24 | Procedure rm_fed
can also be used to iterate through key/item pairs. It uses \
25 | a cursor under the covers.\
26 |
\
6 | When inserting maps into other maps cycles may be created. For example, when map1
contains map2
\
7 | which contains map1
again.\
8 |
\ 10 | RpgMap does not detect cycles. Care should be taken to avoid them. If a cycle is \ 11 | created then that will likely result in corruption and/or a stack overflow error.\ 12 |
\ 13 | \ 14 | '); 15 | -------------------------------------------------------------------------------- /docs/content/example_1.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |\ 6 | The following code creates a new map which is immediately populated with 3 key/item pairs, \ 7 | where the keys are dates and the items are packed decimals.\ 8 |
\ 9 |\ 10 | map = rm_m(\ 15 |
\ 11 | rm_d(d\'2017-01-01\') : rm_p(100.50) :
\ 12 | rm_d(d\'2017-05-01\') : rm_p(50) :
\ 13 | rm_d(d\'2017-07-02\') : rm_p(201.10) );
\ 14 |
\ 16 | An alternative way of creating the same map would be as follows.\ 17 |
\ 18 |\ 19 | map = rm_insert(rm_m() :\ 24 |
\ 20 | rm_d(d\'2017-01-01\') : rm_p(100.50) :
\ 21 | rm_d(d\'2017-05-01\') : rm_p(50) :
\ 22 | rm_d(d\'2017-07-02\') : rm_p(201.10) );
\ 23 |
\
25 | Procedure rm_m
creates a new map, which is immediately \
26 | populated. Procedure rm_insert
inserts the \
27 | key/item pairs into the new map, and returns the new map that was passed as the first \
28 | argument. Procedures that return their first argument, the map/value, can be used for \
29 | "chaining" procedure calls.\
30 |
\
32 | Procedures rm_d
and rm_p
\
33 | create a new RpgMap date value and a new RpgMap packed decimal value, that are inserted into \
34 | the map as a key and an item. Every supported data type has a rm_??
procedure to \
35 | create new values, where ??
is 1 or 2 characters that identify the type.\
36 |
\
38 | RPG values are wrapped into RpgMap values using the rm_??
procedures, \
39 | so that RpgMap can handle values of different types uniformly. Later when these RPG values \
40 | are needed they are unwrapped again using the rm_??_
procedures, \
41 | such as rm_d_
and rm_p_
\
42 | (with trailing underscore).\
43 |
\ 45 | To retrieve the item with key 2017-05-01 one of the following statements can be used.\ 46 |
\ 47 |\ 48 | x = rm_get(map: rm_d(d\'2017-05-01\') ); // supports only one key, \'*f\'/\'*l\'\ 52 |
\ 49 | x = rm__( map: rm_d(d\'2017-05-01\') ); // supports mutiple keys
\ 50 | x = rm__d( map: d\'2017-05-01\' ); // " " " without wrapping
\ 51 |
\
53 | The date argument for rm_get
and rm__
\
54 | is an RpgMap date value that will be automatically disposed (i.e. released, deallocated). See \
55 | Automatic Memory Management) for details.\
56 |
\
58 | Variable x
is a pointer which now points to the RpgMap packed decimal value, \
59 | an opaque data structure, that was created with rm_p
earlier, \
60 | and which is still contained in the map. Expression rm_p_(x)
(rm_p
with \
61 | trailing underscore) converts (unwraps) the RpgMap packed decimal value x
to a real \
62 | RPG packed decimal value.\
63 |
\ 65 | The following statement displays the sum of the items with keys 2017-05-01 and 2017-07-02.\ 66 |
\ 67 |\ 68 | display(%char( rm_p_(rm__d(map:d\'2017-05-01\')) + rm_p_(rm__d(map:d\'2017-07-02\')) ));\ 70 |
\ 69 |
\ 72 | DSPLY 251.1000\ 74 |
\ 73 |
\
75 | When map
is not needed anymore we need to dispose it with rm_dispose
\
76 | to release/deallocate/free the memory it is using. This will also dispose all contained values, automatically \
77 | disposed maps and associated cursors.\
78 |
\ 80 | rm_dispose(map);\ 82 | \ 83 | '); 84 | -------------------------------------------------------------------------------- /docs/content/example_2.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 81 |
\
6 | The following map has composite keys, consisting of an integer and a date. The dates with \
7 | key 5 have the "reversed order" property set (with :0
).\
8 |
\ 10 | map = rm_m(\ 21 |
\ 11 | rm_v( rm_i(1) : rm_d(d\'2017-01-01\' ) ) : rm_p(100.50) :
\ 12 | rm_v( rm_i(1) : rm_d(d\'2017-01-05\' ) ) : rm_p(10) :
\ 13 | rm_v( rm_i(1) : rm_d(d\'2017-02-22\' ) ) : rm_p(50) :
\ 14 | rm_v( rm_i(5) : rm_d(d\'2017-01-01\':0) ) : rm_p(15.9) :
\ 15 | rm_v( rm_i(5) : rm_d(d\'2017-02-02\':0) ) : rm_p(7.5) :
\ 16 | rm_v( rm_i(5) : rm_d(d\'2017-03-03\':0) ) : rm_p(80) :
\ 17 | rm_v( rm_i(7) : rm_d(d\'2017-05-01\' ) ) : rm_p(100) :
\ 18 | rm_v( rm_i(7) : rm_d(d\'2017-06-02\' ) ) : rm_p(1) :
\ 19 | rm_v( rm_i(7) : rm_d(d\'2017-07-03\' ) ) : rm_p(5) );
\ 20 |
\
22 | A composite key is represented with a "vector" (see Vectors), which \
23 | is a special kind of map, created with rm_v
. The keys of a vector must \
24 | be all integers and two vectors are compared in a special way. For example, vectors rm_v(rm_i(1):rm_i(2))
\
25 | and rm_v(rm_i(1))
are considered to be equal. Only the items are specified for rm_v
; \
26 | the keys are implicitly created.\
27 |
\
29 | Iteration is done through cursors, which must first be created with rm_cursor
. \
30 | A cursor maintains a current position within the key/item pairs of a map. The position can be \
31 | set using rm_setll
(set-lower-limit) or rm_setgt
\
32 | (set-greater-than). The next key/item pair can be read with rm_read_next
. \
33 | Procedures rm_key
and rm_item
are \
34 | used to retrieve the current key/item.\
35 |
\ 37 | The following code simply iterates through all key/item pairs and displays them.\ 38 |
\ 39 |\ 40 | c = rm_setll(rm_cursor(map));\ 47 |
\ 41 | dow rm_read_next(c);
\ 42 | display( %char( rm_i_( rm__i(rm_key(c):1) ) ) +
\ 43 | \'/\' + %char( rm_d_( rm__i(rm_key(c):2) ) ) +
\ 44 | \': \' + %char( rm_p_( rm_item(c) ) );
\ 45 | enddo;
\ 46 |
\ 49 | DSPLY 1/2017-01-05: 10.0000\ 59 |
\ 50 | DSPLY 1/2017-02-01: 100.5000
\ 51 | DSPLY 1/2017-02-22: 50.0000
\ 52 | DSPLY 5/2017-03-03: 80.0000
\ 53 | DSPLY 5/2017-02-02: 7.5000
\ 54 | DSPLY 5/2017-01-01: 15.9000
\ 55 | DSPLY 7/2017-05-01: 100.0000
\ 56 | DSPLY 7/2017-06-01: 5.0000
\ 57 | DSPLY 7/2017-06-02: 1.0000
\ 58 |
\ 60 | The cursor should be disposed if it\'s not used anymmore.\ 61 |
\ 62 |\ 63 | rm_dispose(c);\ 65 |
\ 64 |
\ 66 | The following code iterates through all key/item pairs with integer 5, displays each date, \ 67 | and the sum of the items.\ 68 |
\ 69 |\ 70 | sum = 0;\ 78 |
\ 71 | c = rm_setll(rm_cursor(map):rm_v(rm_i(5)));
\ 72 | dow rm_read_next(c:rm_v(rm_i(5)));
\ 73 | sum += rm_p_(rm_item(c));
\ 74 | display(%char(rm_d_(rm__i(rm_key(c):2))));
\ 75 | enddo;
\ 76 | display(%char(sum));
\ 77 |
\ 80 | DSPLY 2017-03-03\ 85 |
\ 81 | DSPLY 2017-02-02
\ 82 | DSPLY 2017-01-01
\ 83 | DSPLY 103.4000
\ 84 |
\
86 | The keys that were passed as argument to rm_setll
and rm_read_next
, \
87 | rm_v(rm_i(5))
, are automatically disposed.\
88 |
\ 90 | The map is disposed, and associated cursors are also disposed.\ 91 |
\ 92 |\ 93 | rm_dispose(map);\ 95 | \ 96 | '); 97 | -------------------------------------------------------------------------------- /docs/content/example_3.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 94 |
\ 6 | The following map represents three loans. Each loan has several attributes such as client \ 7 | name, amount, total payed. A loan can have registered payments, and a call log.\ 8 |
\ 9 |
\ 10 | map = rm_m(\ 43 |
\ 11 |
\ 12 | rm_v( rm_d(d\'2017-01-01\') : rm_i(1) ) : rm_m(
\ 13 | rm_a(\'client name\') : rm_s(\'fransen\') :
\ 14 | rm_a(\'amount\') : rm_p(100.90) :
\ 15 | rm_a(\'payed\') : *null :
\ 16 | rm_a(\'creditstop\') : rm_n(*on) )
\ 17 | :
\ 18 | rm_v( rm_d(d\'2017-05-01\') : rm_i(1) ) : rm_m(
\ 19 | rm_a(\'client name\') : rm_s(\'piet\') :
\ 20 | rm_a(\'amount\') : rm_p(50.00) :
\ 21 | rm_a(\'payed\') : rm_p(20.00) :
\ 22 | rm_a(\'creditstop\') : rm_n(*off) :
\ 23 | rm_a(\'payments\') : rm_m(
\ 24 | rm_z(z\'2017-05-05-16.15.00\') : rm_p(15.00) :
\ 25 | rm_z(z\'2017-05-12-12.00.00\') : rm_p(5.00) ) )
\ 26 | :
\ 27 | rm_v( rm_d(d\'2017-05-01\') : rm_i(2) ) : rm_m(
\ 28 | rm_a(\'client name\') : rm_s(\'jan\') :
\ 29 | rm_a(\'amount\') : rm_p(200.00) :
\ 30 | rm_a(\'payed\') : rm_p(10.50) :
\ 31 | rm_a(\'creditstop\') : rm_n(*off) :
\ 32 | rm_a(\'payments\') : rm_m(
\ 33 | rm_z(z\'2017-05-10-10.00.00\') : rm_p(10.50) ) :
\ 34 | rm_a(\'call log\') : rm_m(
\ 35 | rm_z(z\'2017-05-12-15.10.00\') : rm_v(
\ 36 | rm_t(t\'00.10.05\') : rm_s(\'+1-202-555-0195\') : rm_s(\'+
\ 37 | promised to pay 50 next week\') ) :
\ 38 | rm_z(z\'2017-05-23-11.30.00\') : rm_v(
\ 39 | rm_t(t\'00.02.00\') : rm_s(\'+1-202-555-0195\') : rm_s(\'+
\ 40 | pays tomorrow\') ) ) )
\ 41 | );
\ 42 |
\ 44 | The following code displays each loan\'s client name, all payments, and total call time, \ 45 | from 2017-05-01.\ 46 |
\ 47 |\ 48 | cur1 = rm_sll(rm_cur(map):rm_v(rm_d(d\'2017-05-01\')));\ 76 |
\ 49 | dow rm_rdn(cur1);
\ 50 | k = rm_key(cur1);
\ 51 | i = rm_itm(cur1);
\ 52 | display(rm_s_(rm__a(i:\'client name\')) + \':\');
\ 53 | m = rm__a(i:\'payments\');
\ 54 | if m <> *null;
\ 55 | display(\' payments:\');
\ 56 | cur2 = rm_cur(m);
\ 57 | dow rm_rdn(cur2);
\ 58 | display(\' \' + %char(rm_z_(rm_key(cur2))) +\ 59 | \': \' + %char(rm_p_(rm_itm(cur2))));
\ 60 | enddo;
\ 61 | rm_dis(cur2);
\ 62 | endif;
\ 63 | m = rm__a(i:\'call log\');
\ 64 | if m <> *null;
\ 65 | x = 0;
\ 66 | cur2 = rm_cur(m);
\ 67 | dow rm_rdn(cur2);
\ 68 | x += %diff(rm_t_(rm__i(rm_itm(cur2):1)):t\'00.00.00\':*minutes);
\ 69 | enddo;
\ 70 | rm_dis(cur2);
\ 71 | display(\' call time: \' + %char(x));
\ 72 | endif;
\ 73 | enddo;
\ 74 | rm_dis(map);
\ 75 |
\ 78 | DSPLY piet:\ 87 | \ 88 | '); 89 | -------------------------------------------------------------------------------- /docs/content/examples.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 79 | DSPLY payments:
\ 80 | DSPLY 2017-05-05-16.15.00.000000: 15.0000
\ 81 | DSPLY 2017-05-12-12.00.00.000000: 5.0000
\ 82 | DSPLY jan:
\ 83 | DSPLY payments:
\ 84 | DSPLY 2017-05-10-10.00.00.000000: 10.5000
\ 85 | DSPLY call time: 12
\ 86 |
\ 6 | Many procedures have both a short name and a long(er) name. Examples 1 and 2 use the long names. \ 7 | Example 3 uses the short names.\ 8 |
\ 9 |\
10 | The examples use the following procedure, display
.\
11 |
\ 13 | dcl-proc display;\ 22 | \ 23 | '); 24 | -------------------------------------------------------------------------------- /docs/content/installation.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 14 | dcl-pi *n;
\ 15 | text varchar(500) value;
\ 16 | end-pi;
\ 17 | dcl-s t char(52);
\ 18 | t = text;
\ 19 | dsply t;
\ 20 | end-proc;
\ 21 |
\ 6 | RpgMap is on Github. It\'s installed by putting library RPGMAP on your i. At the moment RpgMap can \ 7 | only be installed by building it from source. The IBM i version used must be at least 7.2.\ 8 |
\ 9 |\
11 | Download RpgMap-1.2.1.zip and put it somewhere on the IFS, e.g. /home/...
\
12 | If you didn\'t already, start QSH (QSHELL, not PASE).
\
13 | Cd into the directory with the zip file.
\
14 | Unzip the file with jar xvf RpgMap-1.2.1.zip
.
\
15 | Cd into directory "RpgMap-1.2.1/src".
\
16 | Start the build with chmod +x BUILD.sh && ./BUILD.sh
.
\
17 | This will create the library (default RPGMAP) and the necessary objects in it, using mostly \
18 | the default system settings such as object owner and authorities.
\
19 | The last message should say "OK; serviceprogram {lib}/RPGMAP has been created.".\
20 |
\
23 | The alternate sort sequence used for values such as rm_aa
\
24 | is determined at build time. Variable SRTSEQ
in build script BUILD.sh can be set to the \
25 | desired sort sequence. By default the RPG module is compiled with altseq(*EXT)
and \
26 | srtseq(*LANGIDSHR)
.\
27 |
\ 6 | In many languages, such as Java or Python, collection types such as maps/dictionaries, \ 7 | lists, etc, are commonly used. They are the workhorses for in-memory data processing.\ 8 |
\ 9 |\ 10 | RpgMap implements a versatile in-memory ordered key/value store, like a Java TreeMap or \ 11 | a Python dict, for use with the RPG programming language. An RpgMap stores key/item pairs. \ 12 | It associates keys with items. The keys and items in an RpgMap can be values such as \ 13 | integers and dates or other RpgMaps. An RpgMap can contain any mix of types. The key/item \ 14 | pairs are always sorted by key. Items can be retrieved by key very fast because of an \ 15 | efficient red-black tree implementation.\ 16 |
\ 17 |\ 18 | An RpgMap may contain duplicate keys.\ 19 |
\ 20 |\ 21 | An RpgMap is simply called a "map" from here on.\ 22 |
\ 23 |\ 24 | Maps support a rich set of operations, such as different ways of populating (new) maps \ 25 | with keys and items, looking up items by key, testing the existence of keys, iterating \ 26 | through key/item pairs using cursors which support set-lower-limit, set-greater-than, \ 27 | read, read-previous, read-equal semantics, etc.\ 28 |
\ 29 |\ 30 | Key/item pairs can be inserted and removed while iterating through a map. The behavior \ 31 | is well defined.\ 32 |
\ 33 |\ 34 | The keys and items in a map can be any mix of maps and values of different types. The \ 35 | supported value types are integer, packed decimal, date, time, timestamp, indicator, \ 36 | (procedure) pointer and character data.\ 37 |
\ 38 |\ 39 | Besides normal character data, there is an extra "string" value type, which is character data \ 40 | in utf-8 format (text). There is also a special map type, "vector", which is used to represent \ 41 | simple lists or sequences. Because of the way vectors are compared with each other they are \ 42 | especially useful as (partial) composite keys (e.g. a key which consists of a date and an integer).\ 43 |
\ 44 |\ 45 | A special type of character data or string conforms to an alternate sort (collating) sequence, \ 46 | such as *langidshr, when compared with the same type (see "altseq"/"srtseq" RPG control spec \ 47 | keywords). Values and maps can have the special "reversed order" property, which reverses their \ 48 | sort order when compared to other values and maps. Character data and strings can have the \ 49 | "case insensitive order" property.\ 50 |
\ 51 |\ 52 | Maps can have one or more attributes. These can be used to store settings and other metadata \ 53 | related to a map.\ 54 |
\ 55 |\ 56 | Most procedures have short names to facilitate compact code. Many procedures also have \ 57 | a long name that is more descriptive.\ 58 |
\ 59 |\ 60 | There are some restrictions. Floating point values and zoned decimals are not supported. \ 61 | Character data and strings can not be longer than 30.000 bytes. Integer values can be int(10) \ 62 | or int(20). Packed decimal values can be packed(14:4), packed(28:8) or packed(46:16).\ 63 |
\ 64 | \ 65 | '); 66 | -------------------------------------------------------------------------------- /docs/content/longprnms.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |\ 6 | Many procedures have a short name and a long name. The short name can be used for compact code \ 7 | and the long(er) name can be used when a more descriptive name is desired.\ 8 |
\ 9 |\ 10 | Below is a list of all procedures that have both a short and long name.\ 11 |
\ 12 |\ 13 | rm_inm : rm_in_map\ 61 | \ 62 | '); 63 | -------------------------------------------------------------------------------- /docs/content/restrict.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 14 | rm_mmm : rm_make_map_manually_disposed
\ 15 | rm_mmi : rm_make_map_immutable
\ 16 | rm_dis : rm_dispose
\ 17 | rm_ins : rm_insert
\ 18 | rm_ins1 : rm_insert_1
\ 19 | rm_insm : rm_insert_map
\ 20 | rm_insc : rm_insert_cond
\ 21 | rm_insc1 : rm_insert_cond_1
\ 22 | rm_inscm : rm_insert_cond_map
\ 23 | rm_insx : rm_insert_excl
\ 24 | rm_insx1 : rm_insert_excl_1
\ 25 | rm_insxm : rm_insert_excl_map
\ 26 | rm_rmv : rm_remove
\ 27 | rm_rmva : rm_remove_all
\ 28 | rm_cmp : rm_compare
\ 29 | rm_cmpeq : rm_compare_eq
\ 30 | rm_cmplt : rm_compare_lt
\ 31 | rm_cmple : rm_compare_le
\ 32 | rm_cmpgt : rm_compare_gt
\ 33 | rm_cmpge : rm_compare_ge
\ 34 | rm_ : rm_set_prop
\ 35 | rm_hky : rm_has_key
\ 36 | rm_hks : rm_has_keys
\ 37 | rm_num : rm_num_keys
\ 38 | rm_hit : rm_has_item
\ 39 | rm_nit : rm_num_items
\ 40 | rm_gik : rm_get_item_key
\ 41 | rm_cpy : rm_copy
\ 42 | rm_cpyd : rm_copy_deep
\ 43 | rm_cur : rm_cursor
\ 44 | rm_sll : rm_setll
\ 45 | rm_sgt : rm_setgt
\ 46 | rm_rdn : rm_read_next
\ 47 | rm_rdp : rm_read_prev
\ 48 | rm_itm : rm_item
\ 49 | rm_slln : rm_setll_read_next
\ 50 | rm_sgtp : rm_setgt_read_prev
\ 51 | rm_hsn : rm_has_next
\ 52 | rm_hsp : rm_has_prev
\ 53 | rm_fed : rm_for_each_do
\ 54 | rm_fedr : rm_for_each_do_rev
\ 55 | rm_scf : rm_set_comp_fun
\ 56 | rm_gcf : rm_get_comp_fun
\ 57 | rm_sav : rm_set_attr_val
\ 58 | rm_gav : rm_get_attr_val
\ 59 | rm_usrd : rm_user_data
\ 60 |
\ 6 | RPG constant RPGMAP_MAXBYTES defines the maximum number of bytes for character and \ 7 | string values, which is 30.000 bytes.\ 8 |
\ 9 |\ 10 | The following RPG constants define the minimum and maximum value for each numeric \ 11 | value type.\ 12 |
\ 13 |\ 14 | RPGMAP_I1_MIN -2147483648\ 25 | \ 26 | '); 27 | -------------------------------------------------------------------------------- /docs/content/rm__.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |
\ 15 | RPGMAP_I1_MAX 2147483647
\ 16 | RPGMAP_I2_MIN -9223372036854775808
\ 17 | RPGMAP_I2_MAX 9223372036854775807
\ 18 | RPGMAP_P1_MIN -9999999999.9999
\ 19 | RPGMAP_P1_MAX 9999999999.9999
\ 20 | RPGMAP_P2_MIN -99999999999999999999.99999999
\ 21 | RPGMAP_P2_MAX 99999999999999999999.99999999
\ 22 | RPGMAP_P3_MIN -999999999999999999999999999999.9999999999999999
\ 23 | RPGMAP_P3_MAX 999999999999999999999999999999.9999999999999999\ 24 |
❘Retrieve item with one or more keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 pointer value options(*nopass)
\ 8 | ...
\ 9 | k10 pointer value options(*nopass)
\ 10 |
\
12 | ● Like rm_get
, but procedures rm__??
retrieve an item using one or more \
13 | keys. There is a version for each data type, so that the keys can be given \
14 | as normal RPG data types (although they can\'t be intermixed).
\
15 | ● When multiple keys are given the item is retrieved through one or more \
16 | nested maps.
\
17 | ● First the item in map
with key equal to the first passed key is retrieved. \
18 | If found and the item is a map and there is a second key passed then the item \
19 | in this map with key equal to the second key is retrieved, etc. Return the last \
20 | item retrieved, or *null
if a key was not found in a map or if there are more \
21 | keys passed than there are nested maps.
\
22 | ● Up to 10 keys can be passed. Parameters k01
through k10
are all \
23 | optional. If none are passed then *null
is returned. Keys that are *null
\
24 | are ignored.
\
25 | ● Use procedure rm__
as a generic procedure which accepts keys of any type. \
26 | Use procedures rm__??
as a shortcut to pass keys as normal RPG values \
27 | of a certain type. For character and string keys up to 200 bytes can be \
28 | passed.
\
29 | ● If there are multiple keys equal to key
then the first one is selected.
\
30 | ● Procedure rm__
disposes all passed keys automatically, unless a key is \
31 | a manually disposed map, or a value/map contained in a map.\
32 |
❘Retrieve item with one or more char. data keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 varchar(200) value options(*nopass)
\ 8 | ...
\ 9 | k10 varchar(200) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more char. data (altseq) keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 varchar(200) value options(*nopass)
\ 8 | ...
\ 9 | k10 varchar(200) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more date keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 date(*iso-) value options(*nopass)
\ 8 | ...
\ 9 | k10 date(*iso-) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more integer keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 int(20) value options(*nopass)
\ 8 | ...
\ 9 | k10 int(20) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more indicator keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 ind value options(*nopass)
\ 8 | ...
\ 9 | k10 ind value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more packed decimal keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 packed(46:16) value options(*nopass)
\ 8 | ...
\ 9 | k10 packed(46:16) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more string keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 varchar(200) ccsid(*utf8) value options(*nopass)
\ 8 | ...
\ 9 | k10 varchar(200) ccsid(*utf8) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more string (altseq) keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 varchar(200) ccsid(*utf8) value options(*nopass)
\ 8 | ...
\ 9 | k10 varchar(200) ccsid(*utf8) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more time keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 time value options(*nopass)
\ 8 | ...
\ 9 | k10 time value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more pointer keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 pointer value options(*nopass)
\ 8 | ...
\ 9 | k10 pointer value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more procedure pointer keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 pointer(*proc) value options(*nopass)
\ 8 | ...
\ 9 | k10 pointer(*proc) value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Retrieve item with one or more timestamp keys
\ 5 | <<pointer\ 11 |
\ 6 | map pointer value
\ 7 | k01 timestamp value options(*nopass)
\ 8 | ...
\ 9 | k10 timestamp value options(*nopass)
\ 10 |
\
12 | ● See rm__
.\
13 |
❘Create a new character data value
\ 5 | <<pointer\ 9 |
\ 6 | value varchar(30000) const
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new character data value, up to 30.000 bytes long.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert character data to RPG character data (100)
\ 5 | <<varchar(100)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(100) const options(*nopass)
\ 8 |
\
10 | ● See rm_a_
.\
11 |
❘Same as rm_a1_, and dispose the character data
\ 5 | <<varchar(100)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(100) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_a1_
. Additionally, value
is immediately disposed.\
11 |
❘Convert character data to RPG character data (1000)
\ 5 | <<varchar(1000)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(1000) const options(*nopass)
\ 8 |
\
10 | ● See rm_a_
.\
11 |
❘Same as rm_a2_, and dispose the character data
\ 5 | <<varchar(1000)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(1000) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_a2_
. Additionally, value
is immediately disposed.\
11 |
❘Convert character data to RPG character data (10000)
\ 5 | <<varchar(10000)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(10000) const options(*nopass)
\ 8 |
\
10 | ● See rm_a_
.\
11 |
❘Same as rm_a2_, and dispose the character data
\ 5 | <<varchar(10000)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(10000) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_a3_
. Additionally, value
is immediately disposed.\
11 |
❘Convert character data to RPG character data
\ 5 | <<varchar(30000)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(30000) const options(*nopass)
\ 8 |
\
10 | ● Return an RPG varchar(30000)
from value
, which must be character data \
11 | or a string. If value
is a string then the raw bytes are returned; \
12 | no text conversion. If value
is *null
then return \'\'
, or default
\
13 | when passed. If value
is not compatible escape message RM00011 (value \
14 | not compatible) is sent.
\
15 | ● Procedures rm_a1_
, rm_a2_
and rm_a3_
are a bit faster because \
16 | of the shorter return value (100, 1000 or 10000).\
17 |
❘Same as rm_a_, and dispose the character data
\ 5 | <<varchar(30000)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(30000) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_a_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new character data value, alt. sort sequence
\ 5 | <<pointer\ 9 |
\ 6 | value varchar(30000) const
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Like rm_a
, but the character data is compared using an alternate sort \
11 | sequence. When two character data values are compared which are both \
12 | created with rm_aa
or rm_aap
the comparison is done using the alternate \
13 | sort sequence, instead of the default. Which sort sequence that is depends on \
14 | the build options that were used, but usually it is *langidshr
.
\
15 | ● Comparing data using an alternate sort sequence may take more resources than \
16 | when the default sort sequence is used.
\
17 | ● Pass opt
to set special property or user data (see rm_
).\
18 |
❘Create a new character data value, alt. sort seq., pointer to data
\ 5 | <<pointer\ 10 |
\ 6 | addr pointer value
\ 7 | size int(10) value
\ 8 | opt int(10) value options(*nopass)
\ 9 |
\
11 | ● Like rm_aa
, but the data is taken from a pointer and a number of bytes (i.e. size).
\
12 | ● The size must be between 1 and 30.000.
\
13 | ● The passed number of bytes (size
) are copied from the address to which \
14 | the pointer (addr
) points.
\
15 | ● Pass opt
to set special property or user data (see rm_
).\
16 |
❘Add an event handler to a map
\ 5 | <<pointer\ 10 |
\ 6 | map pointer value
\ 7 | hproc pointer(*proc) value
\ 8 | usrd pointer value options(*nopass)
\ 9 |
\
11 | ● Add event handler hproc
to the list of event handlers registered \
12 | for map
, and return map
.
\
13 | ● Events are fired when key/item pairs are inserted into and removed \
14 | from map
. When an event is fired then all event handlers added to \
15 | the map are called in the reversed order they were added (last one \
16 | first).
\
17 | ● Procedure hproc
must have the following signature:\
18 |
\ 20 | rtn type: int(10)\ 27 |
\ 21 | par. 1 : event int(10) value
\ 22 | 2 : map pointer value
\ 23 | 3 : key pointer value
\ 24 | 4 : item pointer value
\ 25 | 5 : usrd pointer value
\ 26 |
\
28 | ● Parameter event
is 1
when the "inserted" event has been triggered \
29 | just after a key/item pair has been inserted, or 2
when the "removed" \
30 | event has been triggered just before a key/item pair is removed.
\
31 | ● Parameters key
and item
is the key/item pair that has been inserted, \
32 | or is about to be removed. In the latter case the key and value will be \
33 | removed immediately after all the event handlers have been called. When \
34 | the key and value are removed they\'re disposed (unless they\'re manually \
35 | disposed maps).
\
36 | ● Parameter map
is the map where the event was fired, usrd
is the \
37 | user data that was optionally passed with parameter usrd
when adding \
38 | the event handler with rm_add_event_handler
(or *null
if not passed).
\
39 | ● The handler\'s return value is ignored.
\
40 | ● If the same handler is added multiple times it will be called as many \
41 | times as it was added.
\
42 | ● Event handlers are removed with procedure rm_remove_event_handler
.
\
43 | ● If a map is disposed then no event handlers will be called. Use rm_rmva
\
44 | first to remove all key/value pairs and fire events, then dispose the map.\
45 |
❘Create a new character data value, pointer to data
\ 5 | <<pointer\ 10 |
\ 6 | addr pointer value
\ 7 | size int(10) value
\ 8 | opt int(10) value options(*nopass)
\ 9 |
\
11 | ● Like rm_a
, but the data is taken from a pointer and a number of bytes (i.e. size).
\
12 | ● The size must be between 1 and 30.000.
\
13 | ● The passed number of bytes (size
) are copied from the address to which \
14 | the pointer (addr
) points.
\
15 | ● Pass opt
to set special property or user data (see rm_
).\
16 |
❘obj1 = obj2 ?
rm_compare_eq\ 5 |
\ 6 | <<ind\ 10 |
\ 7 | obj1 pointer value
\ 8 | obj2 pointer value
\ 9 |
\
11 | ● Return *on
if obj1
is equal to obj2
, else return *off
.\
12 |
❘obj1 >= obj2 ?
rm_compare_ge\ 5 |
\ 6 | <<ind\ 10 |
\ 7 | obj1 pointer value
\ 8 | obj2 pointer value
\ 9 |
\
11 | ● Return *on
if obj1
is equal to or greater than obj2
, else return *off
.\
12 |
❘obj1 > obj2 ?
rm_compare_gt\ 5 |
\ 6 | <<ind\ 10 |
\ 7 | obj1 pointer value
\ 8 | obj2 pointer value
\ 9 |
\
11 | ● Return *on
if obj1
is greater than obj2
, else return *off
.\
12 |
❘obj1 <= obj2 ?
rm_compare_le\ 5 |
\ 6 | <<ind\ 10 |
\ 7 | obj1 pointer value
\ 8 | obj2 pointer value
\ 9 |
\
11 | ● Return *on
if obj1
is equal to or less than obj2
, else return *off
.\
12 |
❘obj1 < obj2 ?
rm_compare_lt\ 5 |
\ 6 | <<ind\ 10 |
\ 7 | obj1 pointer value
\ 8 | obj2 pointer value
\ 9 |
\
11 | ● Return *on
if obj1
is less than obj2
, else return *off
.\
12 |
❘Copy map or value
rm_copy\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | obj pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● Return a (shallow) copy of obj
, which must be a map or a value.
\
13 | ● The new map or value has the same properties and attributes as obj
, \
14 | except that a new copy of a map is always mutable. The copy contains \
15 | the same key/item pairs as obj
. The keys/items in the copy that are \
16 | values or automatically disposed maps are copies of the originals in \
17 | obj
. Manually disposed maps are not copied; the copy will contain \
18 | the same instances.
\
19 | ● Event handlers are NOT copied; the copy has no event handlers.
\
20 | ● Return *null
if obj
is *null
.
\
21 | ● Use rm_cpyd
to make a deep copy of a map, \
22 | in which case manually disposed maps are also (deep) copied.
\
23 | ● The new copy is always mutable. Maps contained in obj
that are \
24 | immutable stay immutable and copies of these maps that are included in the copy are also immutable.
\
25 | ● Be aware that when manually disposed maps are not used then rm_cpy
\
26 | and rm_cpyd
have the same effect, i.e. contained maps are copied \
27 | recursively, effectively producing a deep copy. Avoid excessive memory \
28 | use. When only manually disposed maps are used instead of automatically \
29 | disposed maps then rm_cpy
will produce a real shallow copy.
\
30 | ● If key1
and/or key2
are passed and not *null
the copy will only \
31 | contain the key/item pairs from obj
with key equal to or greater than \
32 | key1
, and equal to or less than key2
. Both keys are optional. If \
33 | key1
is not passed or *null
it\'s assumed to be the lowest key. If \
34 | key2
is not passed it\'s assumed to be the same as key1
(if key1
\
35 | is passed). If key2
is *null
it\'s assumed to be the highest key. \
36 | Return an empty map if key1
is greater than key2
, or if only key1
\
37 | is passed with value *null
.
\
38 | ● Ignore key1
/key2
if obj
is a value.
\
39 | ● An alternative way to copy for example an integer value: rm_i(rm_i_(val))
.
\
40 | ● This procedure disposes key1
and key2
automatically, unless \
41 | key1
/key2
is a manually disposed map, or a value/map contained \
42 | in a map.\
43 |
❘Deep copy map or value
rm_copy_deep\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | obj pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● Like rm_cpy
, but returns a deep copy.
\
13 | ● For values, rm_cpyd
has the same effect as rm_cpy
.
\
14 | ● For maps, contained manually disposed maps are copied also, recursively, \
15 | like automatically disposed maps.\
16 |
❘Create a new cursor
rm_cursor\ 5 |
\ 6 | <<pointer\ 10 |
\ 7 | map pointer value
\ 8 | opt char(10) value options(*nopass)
\ 9 |
\
11 | ● Return a new cursor for map
. The cursor is positioned at the beginning \
12 | or the end, depending on whether opt
is \'*b\'
/\'*begin\'
or \'*e\'
/\'*end\'
, \
13 | resp. Optional parameter opt
defaults to \'*b\'
.
\
14 | ● The cursor should be disposed with rm_dis
when it\'s not used anymore. It \
15 | is automatically disposed when map
is disposed.\
16 |
❘Create a new date value
\ 5 | <<pointer\ 9 |
\ 6 | value date(*iso-) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new date value.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a date/timestamp to an RPG date value
\ 5 | <<date(*iso-)\ 9 |
\ 6 | value pointer value
\ 7 | default date(*iso-) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG date
from value
, which must be a date or timestamp.
\
11 | ● If value
is *null
then return *loval
, or default
\
12 | when passed. If value
is not compatible escape message RM00011 (value not \
13 | compatible) is sent.
\
14 | ● A timestamp is converted to a date using BIF %date.\
15 |
❘Same as rm_d_, and dispose the date/timestamp
\ 5 | <<date(*iso-)\ 9 |
\ 6 | value pointer value
\ 7 | default date(*iso-) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_d_
. Additionally, value
is immediately disposed.\
11 |
❘Dispose maps, cursors and values
rm_dispose\ 5 |
\ 6 | <<-\ 11 |
\ 7 | o001 pointer value options(*nopass)
\ 8 | ...
\ 9 | o100 pointer value options(*nopass)
\ 10 |
\
12 | ● Dispose objects o001
thru o100
. Each object can be a map, a cursor \
13 | or a value.
\
14 | ● When an object is disposed its memory is released/freed.
\
15 | ● Use this procedure when a map, cursor or value is not used anymore.
\
16 | ● If a map is disposed then all associated cursors are also disposed.
\
17 | ● If a map is disposed then all its keys and items are also disposed, i.e. \
18 | all contained maps and values are disposed except manually disposed maps, \
19 | which must always be disposed directly using rm_dis
.
\
20 | ● Values and automatically disposed maps that are contained in (have been \
21 | inserted into) a map can not be directly disposed with rm_dis
.
\
22 | ● Send escape message RM00030 if the object to dispose is a value that is \
23 | contained in a map, or is an automatically disposed map that is contained \
24 | in a map.\
25 |
❘For each do
rm_for_each_do\ 5 |
\ 6 | <<pointer\ 13 |
\ 7 | map pointer value
\ 8 | proc pointer(*proc) value
\ 9 | usrd pointer value options(*nopass)
\ 10 | key1 pointer value options(*nopass)
\ 11 | key2 pointer value options(*nopass)
\ 12 |
\
14 | ● Call procedure proc
for each key/item pair in map
, injecting a \
15 | pointer, then return the pointer that was returned with the last call \
16 | to proc
.
\
17 | ● Procedure proc
must have the following signature:\
18 |
\ 20 | rtn type: pointer\ 26 |
\ 21 | par. 1 : key pointer value
\ 22 | 2 : item pointer value
\ 23 | 3 : usrd pointer value
\ 24 | 4 : stop ind
\ 25 |
\
27 | ● Procedure proc
is executed for each key/item pair in map
, starting \
28 | with the lowest key, up to the highest key, or until proc
sets output \
29 | parameter stop
to *on.
\
30 | ● Use rm_fedr
to start with the highest key down to the lowest key.
\
31 | ● Each time proc
is executed the key and item are passed as arguments key
\
32 | and item
. Parameter usrd
is a pointer to data that is user defined and \
33 | can be anything (e.g. a map or a value), or the pointer is *null
. Procedure \
34 | proc
returns this, or another, pointer which is then passed as argument \
35 | usrd
the next time proc is called again. So the return value of proc
\
36 | is used as input for proc
the next time it\'s called. The initial user data \
37 | pointer that is passed the first time proc
is called is passed to rm_fed
\
38 | or rm_fedr
with parameter usrd
.
\
39 | ● Parameter usrd
is optional; if not passed the user data pointer is *null
.
\
40 | ● If no key/item pair is read (and proc
doesn\'t get called) the return \
41 | value will be usrd
, or *null
if usrd
is not passed.
\
42 | ● If key1
and/or key2
are passed then the key/item pairs that are \
43 | processed are equal to or greater than key1
, and equal to or less than \
44 | key2
. Both keys are optional. If key1
is not passed or *null
it\'s \
45 | assumed to be the lowest key. If key2
is not passed it\'s assumed to \
46 | be the same as key1
(if key1
is passed). If key2
is *null
it\'s \
47 | assumed to be the highest key. Read nothing if key1
is greater than \
48 | key2
, or if only key1
is passed with value *null
.
\
49 | ● These procedures dispose key1
and key2
automatically, unless \
50 | key1
/key2
is a manually disposed map, or a value/map contained \
51 | in a map.\
52 |
❘For each do, reversed
rm_for_each_do_rev\ 5 |
\ 6 | <<pointer\ 13 |
\ 7 | map pointer value
\ 8 | proc pointer(*proc) value
\ 9 | usrd pointer value options(*nopass)
\ 10 | key1 pointer value options(*nopass)
\ 11 | key2 pointer value options(*nopass)
\ 12 |
\
14 | ● See rm_fed
.\
15 |
❘Get attribute value
rm_get_attr_val\ 5 |
\ 6 | <<varchar(100) ccsid(*utf8)\ 10 |
\ 7 | map pointer value
\ 8 | attr varchar(100) ccsid(*utf8) value
\ 9 |
\
11 | ● Return the value of attribute attr
of map
, or \'\'
if the \
12 | attribute is not set.\
13 |
❘Get compare function
rm_get_comp_fun\ 5 |
\ 6 | <<pointer\ 9 |
\ 7 | map pointer value
\ 8 |
\
10 | ● Return the current compare function for map
. Return *null
if the default \
11 | function, rm_cmp
, is in effect.\
12 |
❘Retrieve item with a key
\ 5 | <<pointer\ 10 |
\ 6 | map pointer value
\ 7 | key pointer value
\ 8 | opt char(10) value options(*nopass)
\ 9 |
\
11 | ● Return the item of the key/item pair in map
with key equal to key
.
\
12 | ● Return *null
if not found.
\
13 | ● In case there are multiple keys equal to key
then opt
indicates \
14 | which key: \'*f\'
or \'*first\'
for the first one (which is the default), \
15 | or \'*l\'
or \'*last\'
for the last one.
\
16 | ● This procedure disposes key
automatically, unless key
is a manually \
17 | disposed map, or a value/map contained in a map.\
18 |
❘Get item key
rm_get_item_key\ 5 |
\ 6 | <<pointer\ 13 |
\ 7 | map pointer value
\ 8 | item pointer value
\ 9 | opt char(10) value options(*nopass)
\ 10 | key1 pointer value options(*nopass)
\ 11 | key2 pointer value options(*nopass)
\ 12 |
\
14 | ● Return the key of the item in map
that is equal to item
.
\
15 | ● A slow linear search is performed.
\
16 | ● Items are always compared using the default compare function rm_cmp
.
\
17 | ● In case there are multiple items equal to item
then opt
indicates \
18 | which item: \'*f\'
or \'*first\'
for the first one (which is the default), \
19 | or \'*l\'
or \'*last\'
for the last one (key order). Using \'*f\'
/\'*first\'
or \
20 | \'*l\'
/\'*last\'
makes no difference in performance.\
21 | ● If key1
and/or key2
are passed and not *null
then only the items with \
22 | keys equal to or greater than key1
, and equal to or less than key2
, \
23 | will be considered. Both keys are optional. If key1
is not passed or *null
\
24 | it\'s assumed to be the lowest key. If key2
is not passed it\'s assumed to be \
25 | the same as key1
(if key1 is passed). If key2
is *null
it\'s assumed to \
26 | be the highest key. Return *null
if key1
is greater than key2
, or if only \
27 | key1
is passed with value *null
.
\
28 | ● This procedure disposes item
, key1
and key2
automatically, unless they\'re \
29 | a manually disposed map, or a value/map contained in a map.\
30 |
❘Has item?
rm_has_item\ 5 |
\ 6 | <<ind\ 12 |
\ 7 | map pointer value
\ 8 | item pointer value
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● Return *on
if map
has an item that is equal to item
, else return *off
.
\
14 | ● A slow linear search is performed.
\
15 | ● Items are always compared using the default compare function rm_cmp
.
\
16 | ● If key1
and/or key2
are passed and not *null
then only the items with \
17 | keys equal to or greater than key1
, and equal to or less than key2
, \
18 | will be considered. Both keys are optional. If key1
is not passed or *null
\
19 | it\'s assumed to be the lowest key. If key2
is not passed it\'s assumed to be \
20 | the same as key1
(if key1 is passed). If key2
is *null
it\'s assumed to \
21 | be the highest key. Return *off
if key1
is greater than key2
, or if only \
22 | key1
is passed with value *null
.
\
23 | ● This procedure disposes item
, key1
and key2
automatically, unless they\'re \
24 | a manually disposed map, or a value/map contained in a map.\
25 |
❘Has keys?
rm_has_keys\ 5 |
\ 6 | <<ind\ 11 |
\ 7 | map pointer value
\ 8 | key pointer value
\ 9 | opt char(10) value options(*nopass)
\ 10 |
\
12 | ● If opt
is \'*ge\'
or not passed, then return *on
if \
13 | map
has 1 or more keys that are equal to or greater than key
, else return *off
. If opt
\
14 | is \'*le\'
\then return *on
if map
has 1 or more keys that are equal to or less than key
.
\
15 | ● This procedure disposes key
automatically, unless key
is a manually \
16 | disposed map, or a value/map contained in a map.\
17 |
❘Has key?
rm_has_key\ 5 |
\ 6 | <<ind\ 10 |
\ 7 | map pointer value
\ 8 | key pointer value
\ 9 |
\
11 | ● Return *on
if map
has a key that is equal to key
, else return *off
.
\
12 | ● This procedure disposes key
automatically, unless key
is a manually \
13 | disposed map, or a value/map contained in a map.\
14 |
❘Has next?
rm_has_next\ 5 |
\ 6 | <<ind\ 11 |
\ 7 | cur pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● Return *on
if cursor cur
has a next or previous (rm_hsn
/rm_hsp
) \
13 | key/item pair, i.e. whether rm_rdn
/rm_rdp
will return *on
or not.
\
14 | ● If key1
and/or key2
are passed then the next or previous key must be \
15 | equal to or greater than key1
, and equal to or less than key2
, else \
16 | return *off
. Both keys are optional. If key1
is not passed or *null
\
17 | it\'s assumed to be the lowest key. If key2
is not passed it\'s assumed \
18 | to be the same as key1
(if key1
is passed). If key2
is *null
it\'s \
19 | assumed to be the highest key. Always return *off
if key1
is greater \
20 | than key2
, or if only key1
is passed with value *null
.
\
21 | ● These procedures dispose key1
and key2
automatically, unless \
22 | key1
/key2
is a manually disposed map, or a value/map contained \
23 | in a map.\
24 |
❘Has previous?
rm_has_prev\ 5 |
\ 6 | <<ind\ 11 |
\ 7 | cur pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● See rm_hsn
.\
13 |
❘Create a new integer value, 10 digits
\ 5 | <<pointer\ 9 |
\ 6 | value int(10) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new integer value, with 10 digits.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Create a new integer value, 10 digits
\ 5 | <<pointer\ 9 |
\ 6 | value int(10) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_i
.\
11 |
❘Convert a number to an RPG integer value, 10 digits
\ 5 | <<int(10)\ 9 |
\ 6 | value pointer value
\ 7 | default int(10) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_i_
.\
11 |
❘Same as rm_i1_, and dispose the number
\ 5 | <<int(10)\ 9 |
\ 6 | value pointer value
\ 7 | default int(10) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_i1_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new integer value, 20 digits
\ 5 | <<pointer\ 9 |
\ 6 | value int(20) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new integer value, with 20 digits.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a number to an RPG integer value, 20 digits
\ 5 | <<int(20)\ 9 |
\ 6 | value pointer value
\ 7 | default int(20) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG int(20)
from value
, which must be a number.
\
11 | ● See rm_i_
.\
12 |
❘Same as rm_i2_, and dispose the number
\ 5 | <<int(20)\ 9 |
\ 6 | value pointer value
\ 7 | default int(20) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_i2_
. Additionally, value
is immediately disposed.\
11 |
❘Convert a number to an RPG integer value, 10 digits
\ 5 | <<int(10)\ 9 |
\ 6 | value pointer value
\ 7 | default int(10) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG int(10)
from value
, which must be a number.
\
11 | ● If value
is *null
then return 0
, or default
when passed. If value
\
12 | is not a number escape message RM00011 (value not compatible) is sent. \
13 | If the value is too big for the returned integer format then message \
14 | MCH1210 (receiver value too small) is sent.\
15 |
❘Same as rm_i_, and dispose the number
\ 5 | <<int(10)\ 9 |
\ 6 | value pointer value
\ 7 | default int(10) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_i_
. Additionally, value
is immediately disposed.\
11 |
❘In map?
rm_in_map\ 5 |
\ 6 | <<ind\ 9 |
\ 7 | obj pointer value
\ 8 |
\
10 | ● Return *on
if obj
is (contained) in a map, else return *off
.
\
11 | ● Send escape message RM09005 if obj
is not a value or an \
12 | automatically disposed map.\
13 |
❘Insert key/item pairs
rm_insert\ 5 |
\ 6 | <<pointer\ 14 |
\ 7 | map pointer value
\ 8 | k001 pointer value options(*nopass)
\ 9 | i001 pointer value options(*nopass)
\ 10 | ...
\ 11 | k100 pointer value options(*nopass)
\ 12 | i100 pointer value options(*nopass)
\ 13 |
\
15 | ● Insert up to 100 new key/item pairs into map
and return map
.
\
16 | ● The keys and items must be maps or values. Values are automatically \
17 | disposed when their containing map is disposed, or when the key/item \
18 | is removed from the map. Maps that are not created with rm_mm
are \
19 | also automatically disposed, just like values.
\
20 | ● A key/item pair is inserted into a specific slot, depending on the \
21 | key\'s order among the other keys. This slot is fixed and the key\'s \
22 | order should not be affected by changing the key\'s contents and/or \
23 | properties.
\
24 | ● Values and maps that are automatically disposed can only be inserted \
25 | once into a map. When an automatically disposed map or a value is \
26 | inserted into a map and the map/value has already been inserted into \
27 | a map then escape message RM00010/RM00012 is sent.
\
28 | ● Keys can not be *null
.
\
29 | ● Items can be *null
.
\
30 | ● A map is allowed to contain duplicate keys (i.e. keys that are equal). \
31 | If map
already contains one or more keys that are equal to key
then \
32 | key
is inserted at the end. Searching among equal keys is linear \
33 | time, O(n), and lots of duplicates and/or "equal" searches should therefore \
34 | be avoided.
\
35 | ● Starting at the second argument, every even and uneven argument corresponds \
36 | to a key/item pair that is to be inserted. Pairs where the key is *null
\
37 | are ignored.
\
38 | ● Items which were not inserted (because no key was specified) will be \
39 | disposed, unless the item is a manually disposed map, or a value/map \
40 | contained in a map.\
41 |
❘Insert 1 key/item pair
rm_insert_1\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | map pointer value
\ 8 | key pointer value options(*nopass)
\ 9 | item pointer value options(*nopass)
\ 10 |
\
12 | ● Like rm_ins
, but with only one key/item pair.
\
13 | ● This is the faster version when only one key/item pair needs \
14 | to be inserted.\
15 |
❘Insert key/item pairs, conditionally
rm_insert_cond\ 5 |
\ 6 | <<pointer\ 14 |
\ 7 | map pointer value
\ 8 | k001 pointer value options(*nopass)
\ 9 | i001 pointer value options(*nopass)
\ 10 | ...
\ 11 | k100 pointer value options(*nopass)
\ 12 | i100 pointer value options(*nopass)
\ 13 |
\
15 | ● Like rm_ins
, but a key/item pair is only inserted if there is \
16 | no key in map
that is equal to the key to be inserted.
\
17 | ● Keys and items that are not inserted are disposed automatically, \
18 | unless they are manually disposed maps, or values/maps contained \
19 | in a map.\
20 |
❘Insert 1 key/item pair, conditionally
rm_insert_cond_1\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | map pointer value
\ 8 | key pointer value options(*nopass)
\ 9 | item pointer value options(*nopass)
\ 10 |
\
12 | ● Like rm_insc
, but with only one key/item pair.
\
13 | ● This is the faster version when only one key/item pair needs \
14 | to be inserted.\
15 |
❘Insert key/item pairs, conditionally, from map
rm_insert_cond_map\ 5 |
\ 6 | <<pointer\ 12 |
\ 7 | map pointer value
\ 8 | map2 pointer value
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● Like rm_insm
, but a key/item pair is only inserted if there is \
14 | no key in map
that is equal to the key to be inserted.\
15 |
❘Insert key/item pairs, from map
rm_insert_map\ 5 |
\ 6 | <<pointer\ 12 |
\ 7 | map pointer value
\ 8 | map2 pointer value
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● Like rm_ins
, but the key/item pairs to insert are contained in map2
.
\
14 | ● The values and automatically disposed maps in map2
that are to be \
15 | inserted are not inserted directly, but instead a copy is made (rm_cpy
) \
16 | that is actually inserted. Manually disposed maps are not copied; they\'re \
17 | inserted directly.
\
18 | ● If key1
and/or key2
are passed and not *null
then only the key/item \
19 | pairs in map2
with key equal to or greater than key1
, and equal to \
20 | or less than key2
, will be inserted. Both keys are optional. If key1
\
21 | is not passed or *null
it\'s assumed to be the lowest key. If key2
is \
22 | not passed it\'s assumed to be the same as key1
(if key1
is passed). \
23 | If key2
is *null
it\'s assumed to be the highest key. Nothing is \
24 | inserted if key1
is greater than key2
, or if only key1
is passed \
25 | with value *null
.
\
26 | ● This procedure disposes key1
and key2
automatically, unless \
27 | key1
/key2
is a manually disposed map, or a value/map contained \
28 | in a map.
\
29 | ● This procedure does not dispose map2
or it\'s keys/items.\
30 |
❘Insert key/item pairs, exclusive
rm_insert_excl\ 5 |
\ 6 | <<pointer\ 14 |
\ 7 | map pointer value
\ 8 | k001 pointer value options(*nopass)
\ 9 | i001 pointer value options(*nopass)
\ 10 | ...
\ 11 | k100 pointer value options(*nopass)
\ 12 | i100 pointer value options(*nopass)
\ 13 |
\
15 | ● Like rm_ins
, but before a key/item pair is inserted all key/item \
16 | pairs with a key equal to the key to be inserted are removed first \
17 | (i.e. they\'re replaced).\
18 |
❘Insert 1 key/item pair, exclusive
rm_insert_excl_1\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | map pointer value
\ 8 | key pointer value options(*nopass)
\ 9 | item pointer value options(*nopass)
\ 10 |
\
12 | ● Like rm_insx
, but with only one key/item pair.
\
13 | ● This is the faster version when only one key/item pair needs \
14 | to be inserted.\
15 |
❘Insert key/item pairs, exclusive, from map
rm_insert_excl_map\ 5 |
\ 6 | <<pointer\ 12 |
\ 7 | map pointer value
\ 8 | map2 pointer value
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● Like rm_insm
, but before a key/item pair is inserted all key/item \
14 | pairs with a key equal to the key to be inserted are removed first.\
15 |
❘Is character data?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is character data, else return *off
.\
10 |
❘Is character data with alt. sort seq.?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is character data with alt. sort seq., else return *off
.\
10 |
❘Is date?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a date, else return *off
.\
10 |
❘Is any integer?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is any integer type, else return *off
.\
10 |
❘Is integer with 10 digits?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is an integer with 10 digits, else return *off
.\
10 |
❘Is integer with 20 digits?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is an integer with 20 digits, else return *off
.\
10 |
❘Is map?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a map/vector, else return *off
.\
10 |
❘Is manually disposed map?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a manually disposed map, else return *off
.\
10 |
❘Is indicator?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is an indicator, else return *off
.\
10 |
❘Is any packed decimal?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is any packed decimal type, else return *off
.\
10 |
❘Is packed decimal with 10.4 digits?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a packed decimal with 10.4 digits, else return *off
.\
10 |
❘Is packed decimal with 20.8 digits?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a packed decimal with 20.8 digits, else return *off
.\
10 |
❘Is packed decimal with 30.16 digits?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a packed decimal with 30.16 digits, else return *off
.\
10 |
❘Is string?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a string, else return *off
.\
10 |
❘Is string with alt. sort seq.?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a string with alt. sort seq., else return *off
.\
10 |
❘Is time?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a time, else return *off
.\
10 |
❘Is vector?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a vector, else return *off
.\
10 |
❘Is pointer?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a pointer, else return *off
.\
10 |
❘Is procedure pointer?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a procedure pointer, else return *off
.\
10 |
❘Is timestamp?
\ 5 | <<ind\ 8 |
\ 6 | obj pointer value
\ 7 |
\
9 | ● Return *on
if obj
is a timestamp, else return *off
.\
10 |
❘Return current item
rm_item\ 5 |
\ 6 | <<pointer\ 9 |
\ 7 | cur pointer value
\ 8 |
\
10 | ● Return the current item for cursor cur
, after calling rm_rdn
or rm_rdp
.\
11 | ● The current item may be *null
.
\
12 | ● Call rm_key
to check whether there is a current key/item pair.\
13 |
❘Return current key
\ 5 | <<pointer\ 8 |
\ 6 | cur pointer value
\ 7 |
\
9 | ● Return the current key for cursor cur
, after calling rm_rdn
or rm_rdp
.
\
10 | ● Return *null
if there is no current key/item pair.\
11 |
❘Create a new map, automatically disposed
\ 5 | <<pointer\ 12 |
\ 6 | k001 pointer value options(*nopass)
\ 7 | i001 pointer value options(*nopass)
\ 8 | ...
\ 9 | k100 pointer value options(*nopass)
\ 10 | i100 pointer value options(*nopass)
\ 11 |
\
13 | ● Create a new map and return a pointer to it.
\
14 | ● The map should be disposed - with rm_dis
\
15 | - when it\'s not needed anymore. If the map is inserted into a map as a key or item it will \
16 | be automatically disposed when the containing map is disposed or when \
17 | the key/item is removed, and rm_dis
can not be used \
18 | anymore to dispose the map.
\
19 | ● Like a value, an automatically disposed map can be inserted into \
20 | (contained in) one map only, i.e. it can be inserted only once (even \
21 | when inserting into the same map). Escape message RM00010 will be sent \
22 | if an automatically disposed map is inserted into a map for a second time.
\
23 | ● The new map can be immediately populated with key/item pairs by passing \
24 | the keys and items as arguments. This is the same as calling rm_ins1
\
25 | repeatedly, with arguments 1 and 2 as the first key and item, resp., \
26 | arguments 3 and 4 as the second key and item, etc. Up to 100 key/item \
27 | pairs can be passed. An item is optional (or *null
). Key/items \
28 | of which the key is *null
are ignored.
\
29 | ● Items which were not inserted because no key was specified will be \
30 | disposed, unless the item is a manually disposed map, or a value/map \
31 | contained in a map.\
32 |
❘Create a new map, manually disposed
\ 5 | <<pointer\ 12 |
\ 6 | k001 pointer value options(*nopass)
\ 7 | i001 pointer value options(*nopass)
\ 8 | ...
\ 9 | k100 pointer value options(*nopass)
\ 10 | i100 pointer value options(*nopass)
\ 11 |
\
13 | ● Same as rm_m
except that the new map is not automatically disposed \
14 | and must always be manually disposed with rm_dis
. However, unlike automatically disposed \
15 | maps, a manually disposed map can be inserted into multiple maps.\
16 |
❘Make map immutable
rm_make_map_immutable\ 5 |
\ 6 | <<pointer\ 10 |
\ 7 | map pointer value
\ 8 | opt char(10) value options(*nopass)
\ 9 |
\
11 | ● Make map
immutable, and return map
.
\
12 | ● An immutable map can not be mutated, i.e. no key/item pairs can be inserted \
13 | into or removed from the map. If a key/item pair is inserted into or removed \
14 | from an immutable map then escape message RM00005 is sent.
\
15 | ● All contained automatically disposed maps (thus including vectors) are also \
16 | made immutable, recursively.
\
17 | ● If opt
is passed and is \'*mm\'
then all contained manually \
18 | disposed maps are also made immutable, recursively, like contained automatically disposed maps.
\
19 | ● If map
is already immutable then this operation has no effect.
\
20 | ● This operation can not be undone; an immutable map can not be made mutable again.
\
21 | ● When a map is copied (rm_cpy
) then the new copy is mutable.\
22 |
❘Make map manually disposed
rm_make_map_manually_disposed\ 5 |
\ 6 | <<pointer\ 9 |
\ 7 | map pointer value
\ 8 |
\
10 | ● Make map
a manually disposed map, and return map
.
\
11 | ● Send escape message RM00051 if map
is not an automatically disposed map, \
12 | or if map
is a vector.
\
13 | ● This operation can not be undone; a manually disposed map can not be made \
14 | automatically disposed.\
15 |
❘Create a new indicator value
\ 5 | <<pointer\ 9 |
\ 6 | value ind value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new indicator value.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert an indicator to an RPG indicator value
\ 5 | <<ind\ 9 |
\ 6 | value pointer value
\ 7 | default ind value options(*nopass)
\ 8 |
\
10 | ● Return an RPG ind
from value
, which must be an indicator.
\
11 | ● If value
is *null
then return *off
, or default
\
12 | when passed. If value
is not compatible escape message RM00011 (value not \
13 | compatible) is sent.\
14 |
❘Same as rm_n_, and dispose the indicator
\ 5 | <<ind\ 9 |
\ 6 | value pointer value
\ 7 | default ind value options(*nopass)
\ 8 |
\
10 | ● Same as rm_n_
. Additionally, value
is immediately disposed.\
11 |
❘Number of items
rm_num_items\ 5 |
\ 6 | <<uns(20)\ 12 |
\ 7 | map pointer value
\ 8 | item pointer value
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● Return the number of items in map
that are equal to item
.
\
14 | ● Items are always compared using the default compare function rm_cmp
.
\
15 | ● If key1
and/or key2
are passed and not *null
then only the items with \
16 | keys equal to or greater than key1
, and equal to or less than key2
, \
17 | will be considered. Both keys are optional. If key1
is not passed or *null
\
18 | it\'s assumed to be the lowest key. If key2
is not passed it\'s assumed to be \
19 | the same as key1
(if key1 is passed). If key2
is *null
it\'s assumed to \
20 | be the highest key. Return 0
if key1
is greater than key2
, or if only \
21 | key1
is passed with value *null
.
\
22 | ● This procedure disposes item
, key1
and key2
automatically, unless they\'re \
23 | a manually disposed map, or a value/map contained in a map.\
24 |
❘Number of key/item pairs
rm_num_keys\ 5 |
\ 6 | <<uns(20)\ 11 |
\ 7 | map pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● Return the number of key/item pairs in map
with key equal to or \
13 | greater than key1
, and equal to or less than key2
. Both keys \
14 | are optional. If key1
is not passed or *null
it\'s assumed to be \
15 | the lowest key. If key2
is not passed it\'s assumed to be the same \
16 | as key1
(if key1
is passed). If key2
is *null
it\'s assumed to \
17 | be the highest key. Return 0
if key1
is greater than key2
, or \
18 | only key1
is passed with value *null
.
\
19 | ● This procedure is not efficient. Unless both keys are *null
or not \
20 | passed (i.e. all key/item pairs) it counts the number of keys each \
21 | time it\'s called (no caching).
\
22 | ● This procedure disposes key1
and key2
automatically, unless \
23 | key1
/key2
is a manually disposed map, or a value/map contained \
24 | in a map.\
25 |
❘Create a new packed decimal value, 10.4 digits
\ 5 | <<pointer\ 9 |
\ 6 | value packed(14:4) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new packed decimal value, with 10.4 digits.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Create a new packed decimal value, 10.4 digits
\ 5 | <<pointer\ 9 |
\ 6 | value packed(14:4) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_p
.\
11 |
❘Convert a number to an RPG packed decimal value, 10.4 digits
\ 5 | <<packed(14:4)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(14:4) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_p_
.\
11 |
❘Same as rm_p_, and dispose the number
\ 5 | <<packed(14:4)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(14:4) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_p1_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new packed decimal value, 20.8 digits
\ 5 | <<pointer\ 9 |
\ 6 | value packed(28:8) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new packed decimal value, with 20.8 digits.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a number to an RPG packed decimal value, 20.8 digits
\ 5 | <<packed(28:8)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(28:8) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG packed(28:8)
from value
, which must be a number.
\
11 | ● See rm_p_
.\
12 |
❘Same as rm_p2_, and dispose the number
\ 5 | <<packed(28:8)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(28:8) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_p2_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new packed decimal value, 30.16 digits
\ 5 | <<pointer\ 9 |
\ 6 | value packed(46:16) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new packed decimal value, with 30.16 digits.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a number to an RPG packed decimal value, 30.16 digits
\ 5 | <<packed(46:16)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(46:16) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG packed(46:16)
from value
, which must be a number.
\
11 | ● See rm_p_
.\
12 |
❘Same as rm_p3_, and dispose the number
\ 5 | <<packed(46:16)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(46:16) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_p3_
. Additionally, value
is immediately disposed.\
11 |
❘Convert a number to an RPG packed decimal value, 10.4 digits
\ 5 | <<packed(14:4)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(14:4) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG packed(14:4)
from value
, \
11 | which must be a number. If value
is *null
then return 0
, or default
\
12 | when passed. If value
is not a number escape message RM00011 (value not \
13 | compatible) is sent. If the value is too big for the returned packed \
14 | decimal format then message MCH1210 (receiver value too small) is sent.\
15 |
❘Same as rm_p_, and dispose the number
\ 5 | <<packed(14:4)\ 9 |
\ 6 | value pointer value
\ 7 | default packed(14:4) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_p_
. Additionally, value
is immediately disposed.\
11 |
❘Read next key/item pair
rm_read_next\ 5 |
\ 6 | <<ind\ 11 |
\ 7 | cur pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● Call rm_rdn
to read the next key/item pair for cursor cur
, or \
13 | call rm_rdp
to read the previous key/item pair. The next/previous \
14 | pair becomes the current key/item pair. Procedures rm_key
and \
15 | rm_itm
are used to read the current key or item, resp.
\
16 | ● Return *on
if there was a next or previous key/item. Return *off
if \
17 | the cursor is at the end or the beginning, in which case there is no current key/item anymore.
\
18 | ● Key/item pairs can be removed while a cursor iterates over them. \
19 | If the current key/item pair is removed from the map then there is no \
20 | current key/item pair anymore, and rm_key
and rm_itm
will return \
21 | *null
. If rm_rdn
was used to read the current key/item the cursor is \
22 | positioned just before the key/item pair that comes after the removed \
23 | key/item. If rm_rdp
was used the cursor is positioned just after the \
24 | key/item pair that comes before the removed key/item. Procedures rm_rdn
\
25 | and rm_rdp
must be used to get a current key/item pair again. The cursor \
26 | is positioned at the end or beginning, resp., when there is no next or \
27 | previous pair anymore.
\
28 | ● If key1
and/or key2
are passed then the next or previous key must be \
29 | equal to or greater than key1
, and equal to or less than key2
, else \
30 | return *off
(the cursor is at the end/beginning and there is no current \
31 | key/item anymore). Both keys are optional. If key1
is not passed or \
32 | *null
it\'s assumed to be the lowest key. If key2
is not passed it\'s \
33 | assumed to be the same as key1
(if key1
is passed). If key2
is \
34 | *null
it\'s assumed to be the highest key. Always return *off
if key1
\
35 | is greater than key2
, or if only key1
is passed with value *null
.
\
36 | ● These procedures dispose key1
and key2
automatically, unless \
37 | key1
/key2
is a manually disposed map, or a value/map contained \
38 | in a map.\
39 |
❘Read previous key/item pair
rm_read_prev\ 5 |
\ 6 | <<ind\ 11 |
\ 7 | cur pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● See rm_rdn
.\
13 |
❘Remove an event handler from a map
\ 5 | <<pointer\ 9 |
\ 6 | map pointer value
\ 7 | hproc pointer(*proc) value
\ 8 |
\
10 | ● Remove event handler hproc
from the list of event handlers registered \
11 | for map
, and return map
.
\
12 | ● If the handler was added mutiple times then only the last one added \
13 | is removed.
\
14 | ● Do nothing if the handler isn\'t found.\
15 |
❘Remove key/item pair
rm_remove\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | map pointer value
\ 8 | key pointer value
\ 9 | opt char(10) value options(*nopass)
\ 10 |
\
12 | ● Remove the key/item pair with key equal to key
from map
, if \
13 | found, and return map
. If not found do nothing, and return map
.
\
14 | ● If the key and/or item is a value or an automatically disposed map \
15 | then they\'re disposed.
\
16 | ● In case there are multiple keys equal to key
then opt
indicates \
17 | which key: \'*f\'
or \'*first\'
for the first one (which is the default), \
18 | or \'*l\'
or \'*last\'
for the last one.
\
19 | ● This procedure disposes key
automatically, unless key
is a manually \
20 | disposed map, or a value/map contained in a map.\
21 |
❘Remove all key/item pairs
rm_remove_all\ 5 |
\ 6 | <<pointer\ 11 |
\ 7 | map pointer value
\ 8 | key1 pointer value options(*nopass)
\ 9 | key2 pointer value options(*nopass)
\ 10 |
\
12 | ● Like rm_rmv
, but all key/item pairs with key equal to or greater \
13 | than key1
, and equal to or less than key2
are removed from map
.
\
14 | ● Both keys are optional. If key1
is not passed or *null
it\'s assumed \
15 | to be the lowest key. If key2
is not passed it\'s assumed to be the \
16 | same as key1
(if key1
is passed). If key2
is *null
it\'s assumed \
17 | to be the highest key. Remove nothing if key1
is greater than key2
, \
18 | or if only key1
is passed with value *null
.
\
19 | ● This procedure disposes key1
and key2
automatically, unless \
20 | key1
/key2
is a manually disposed map, or a value/map contained in \
21 | a map.\
22 |
❘Create a new string value
\ 5 | <<pointer\ 9 |
\ 6 | value varchar(30000) ccsid(*utf8) const
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new string value, up to 30.000 bytes long.
\
11 | ● A string is character data (text) in utf-8 format.
\
12 | ● The raw bytes can be accessed with rm_a*_
.
\
13 | ● Pass opt
to set special property or user data (see rm_
).
\
14 | ● The argument for parameter value
is converted to utf-8 when it\'s CCSID is \
15 | not 65535. Each utf-8 character consists of one to four bytes. This means care \
16 | should be taken that the converted value does not exceed 30.000 bytes.\
17 |
❘Convert string to RPG utf-8 character data (100)
\ 5 | <<varchar(100) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(100) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● See rm_s_
.\
11 |
❘Same as rm_s1_, and dispose the string
\ 5 | <<varchar(100) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(100) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_s1_
. Additionally, value
is immediately disposed.\
11 |
❘Convert string to RPG utf-8 character data (1000)
\ 5 | <<varchar(1000) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(1000) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● See rm_s_
.\
11 |
❘Same as rm_s2_, and dispose the string
\ 5 | <<varchar(1000) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(1000) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_s2_
. Additionally, value
is immediately disposed.\
11 |
❘Convert string to RPG utf-8 character data (10000)
\ 5 | <<varchar(10000) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(10000) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● See rm_s_
.\
11 |
❘Same as rm_s3_, and dispose the string
\ 5 | <<varchar(10000) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(10000) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_s3_
. Additionally, value
is immediately disposed.\
11 |
❘Convert string to RPG utf-8 character data
\ 5 | <<varchar(30000) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(30000) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● Return an RPG varchar(30000)
in utf-8 format from value
, which must \
11 | be a string. If value
is *null
then return \'\'
, or default
when \
12 | passed. If value
is not compatible escape message RM00011 (value \
13 | not compatible) is sent.
\
14 | ● Procedures rm_s1_
, rm_s2_
and rm_s3_
are a bit faster because \
15 | of the shorter return value (100, 1000 or 10000).\
16 |
❘Same as rm_s_, and dispose the string
\ 5 | <<varchar(30000) ccsid(*utf8)\ 9 |
\ 6 | value pointer value
\ 7 | default varchar(30000) ccsid(*utf8) const options(*nopass)
\ 8 |
\
10 | ● Same as rm_s_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new string value, alt. sort sequence
\ 5 | <<pointer\ 9 |
\ 6 | value varchar(30000) ccsid(*utf8) const
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Like rm_s
, but the string is compared using an alternate sort sequence. \
11 | When two strings are compared which are both created with rm_sa
\
12 | or rm_sab
the comparison is done using the alternate sort sequence, \
13 | instead of the default. Which sort sequence depends on the build options \
14 | that were used, but usually it is *langidshr
.
\
15 | ● Comparing strings using the alternate sort sequence takes considerably \
16 | more resources than normal comparisons. Strings must be converted \
17 | to the job CCSID first before they can be compared using the alternate \
18 | sort sequence.
\
19 | ● Pass opt
to set special property or user data (see rm_
).\
20 |
❘Create a new string value, alt. sort seq., from binary
\ 5 | <<pointer\ 9 |
\ 6 | value varchar(30000) const
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Like rm_sa
, but value
passes the raw bytes that is already in utf-8 format.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Set attribute values
rm_set_attr_val\ 5 |
\ 6 | <<pointer\ 14 |
\ 7 | map pointer value
\ 8 | a001 varchar(100) ccsid(*utf8) value options(*nopass)
\ 9 | v001 varchar(100) ccsid(*utf8) value options(*nopass)
\ 10 | ...
\ 11 | a100 varchar(100) ccsid(*utf8) value options(*nopass)
\ 12 | v100 varchar(100) ccsid(*utf8) value options(*nopass)
\ 13 |
\
15 | ● Set up to 100 attributes of map
to a value and return map
.
\
16 | ● Each map can have one or more attributes set to a value, where \
17 | each attribute has an utf-8 name, and an utf-8 value, both max. \
18 | 100 bytes. There is no restriction on attribute names and values.
\
19 | ● The first attribute name and value is passed with parameters 2 and 3, \
20 | a001
and v001
, the second with a002
and v002
, etc.
\
21 | ● Send escape message RM00102 if an attribute name is blank or empty.
\
22 | ● If a value is not passed or it is blank or empty then the attribute \
23 | is "unset".
\
24 | ● If no attribute names or values are passed at all (i.e. only map
\
25 | is passed) then every attribute of map
is unset (all are cleared).
\
26 | ● Attributes are used to store settings and meta data that is used \
27 | by different software modules/applications, either built-in or external. \
28 | Attributes should be named "module-name" where module is the name of the \
29 | module or function and name is the attribute name. The module\'s docs \
30 | should specify the attributes that are used and their meaning.
\
31 | ● Attribute names starting with "_" (underscore) should not be used \
32 | as these are reserved for RpgMap.\
33 |
❘Create a new string value, from binary
\ 5 | <<pointer\ 9 |
\ 6 | value varchar(30000) const
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Like rm_s
, but value
passes the raw bytes that is already in utf-8 format.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Set compare function
rm_set_comp_fun\ 5 |
\ 6 | <<pointer\ 10 |
\ 7 | map pointer value
\ 8 | comp pointer(*proc) value
\ 9 |
\
11 | ● Set the compare function of map
, which must be empty, to comp
, \
12 | and return map
. Send escape messsage RM00041 if map
is not empty.
\
13 | ● The compare function of map
determines how the keys in map
are \
14 | compared/ordered. Normally rm_cmp
is used as the compare function, \
15 | but this can be overridden with another compare function, comp
, for \
16 | a specific map. When two keys that are both maps are compared, the \
17 | order in which the keys and items are compared is determined by the \
18 | compare functions of the two maps. But when two keys or items, from \
19 | these two maps, are compared then the compare function of the containing \
20 | map is used. Unless this behavior is changed with another \
21 | compare function.
\
22 | ● Procedure comp
must have the following signature:\
23 |
\ 25 | rtn type: int(10)\ 29 |
\ 26 | par. 1 : obj1 pointer value
\ 27 | 2 : obj2 pointer value
\ 28 |
\
30 | ● Procedure comp
compares obj1
and obj2
, which can be *null
or \
31 | a value or a map, and returns 0
of they\'re equal, -1
if obj1
is \
32 | less than obj2, or 1
if obj1
is greater than obj2
.
\
33 | ● If comp
returns something else than 0
, 1
or -1
then the comparison \
34 | falls back to rm_cmp
.
\
35 | ● If comp
is *null
then rm_cmp
is reset to be used as the compare \
36 | function again.
\
37 | ● The following is a simple example of a comp
procedure body, which \
38 | has the effect that the sort order is reversed: return rm_cmp(obj1:obj2)*-1;
.\
39 |
❘Set greater than
rm_setgt\ 5 |
\ 6 | <<pointer\ 10 |
\ 7 | cur pointer value
\ 8 | key pointer value options(*nopass)
\ 9 |
\
11 | ● See rm_sll
.\
12 |
❘Set greater than, read previous
rm_setgt_read_prev\ 5 |
\ 6 | <<ind\ 12 |
\ 7 | cur pointer value
\ 8 | pos ind options(*nopass:*omit)
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● Analogous to rm_slln
, this procedure combines rm_sgt
and \
14 | rm_rdp
into one.
\
15 | ● Each time rm_sgtp
is called: ① if pos
is *on
the cursor is \
16 | positioned with rm_sgt
on key1
, ② pos
is set to *off
, ③ \
17 | rm_rdp
is called with key1
and key2
to read the previous \
18 | key/item pair, ④ the result of calling rm_rdp
is returned.
\
19 | ● Parameter key1
is passed as argument key
to rm_sgt
and key1
\
20 | and key2
are passed to rm_rdp
. See the docs for rm_sgt
and \
21 | rm_rdp
on how optional parameters key1
and key2
are specified.
\
22 | ● The following code loops through all keys equal to d\'2017-01-01\'
, \
23 | but backwards.\
24 |
\ 26 | pos = *on;\ 31 |
\ 27 | dow rm_sgtp(cur:pos:rm_d(d\'2017-01-01\')); // \'pos\' is set to *off
\ 28 | ... // set \'pos\' to *on to trigger \'rm_sgt\' again while looping
\ 29 | enddo;
\ 30 |
\
32 | ● If pos
is not passed or is *OMITted then the procedure behaves as if \
33 | pos
would have been passed with value *on
. This can be used to position \
34 | the cursor and read the previous key/item pair in one call without having \
35 | to provide an indicator field.
\
36 | ● This procedure disposes key1
and key2
automatically, unless \
37 | key1
/key2
is a manually disposed map, or a value/map contained \
38 | in a map.\
39 |
❘Set lower limit
rm_setll\ 5 |
\ 6 | <<pointer\ 10 |
\ 7 | cur pointer value
\ 8 | key pointer value options(*nopass)
\ 9 |
\
11 | ● Position cursor cur
on key
and return cur
.
\
12 | ● Call rm_sll
to position the cursor just before the lowest key that is equal \
13 | to or greater than key
. Call rm_sgt
to position the cursor just after the \
14 | highest key that is equal to or less than key
. If key
is *null
or not passed \
15 | then the cursor is positioned at the beginning or the end, resp.
\
16 | ● After calling one of these procedures cursor cur
has no current key/item pair.
\
17 | ● Call rm_rdn
or rm_rdp
to read the next or previous key/item pair, resp., \
18 | which then becomes the current key/value pair.
\
19 | ● If rm_sll
is called and the next key/item pair is removed from the map the \
20 | cursor is positioned just after the previous pair. If rm_sgt
is called and \
21 | the previous key/item pair is removed from the map the cursor is positioned \
22 | just before the next pair.
\
23 | ● If rm_sll
is called and there is no key equal to or greater, or if rm_sgt
\
24 | is called and there is no key equal to or less, the cursor is positioned at the end or beginning resp.
\
25 | ● These procedures dispose key
automatically, unless key
is a manually \
26 | disposed map, or a value/map contained in a map.\
27 |
❘Set lower limit, read next
rm_setll_read_next\ 5 |
\ 6 | <<ind\ 12 |
\ 7 | cur pointer value
\ 8 | pos ind options(*nopass:*omit)
\ 9 | key1 pointer value options(*nopass)
\ 10 | key2 pointer value options(*nopass)
\ 11 |
\
13 | ● This procedure combines rm_sll
and rm_rdn
into one, so that \
14 | one expression enables both positioning the cursor and repeatedly \
15 | reading the next key/item pair. Positioning is only done when \
16 | input/output parameter pos
is *on
, which is set to *off
automatically \
17 | when rm_slln
is called. This parameter should be *on
the first time \
18 | rm_slln
is called to trigger the positioning.
\
19 | ● Each time rm_slln
is called: ① if pos
is *on
the cursor is \
20 | positioned with rm_sll
on key1
, ② pos
is set to *off
, ③ \
21 | rm_rdn
is called with key1
and key2
to read the next key/item \
22 | pair, ④ the result of calling rm_rdn
is returned.
\
23 | ● When doing a read-equal (i.e. when specifying only key1
for rm_rdn
\
24 | or rm_rdp
), key1
must be specified twice (rm_sll
and rm_rdn
). \
25 | Using this method, key1
needs to be specified only once, but at the \
26 | cost of the extra indicator which makes the code a little more complex.
\
27 | ● Parameter key1
is passed as argument key
to rm_sll
and key1
\
28 | and key2
are passed to rm_rdn
. See the docs for rm_sll
and \
29 | rm_rdn
on how optional parameters key1
and key2
are specified.
\
30 | ● The following code loops through all keys equal to d\'2017-01-01\'
.\
31 |
\ 33 | pos = *on;\ 38 |
\ 34 | dow rm_slln(cur:pos:rm_d(d\'2017-01-01\')); // \'pos\' is set to *off
\ 35 | ... // set \'pos\' to *on to trigger \'rm_sll\' again while looping
\ 36 | enddo;
\ 37 |
\
39 | ● If pos
is not passed or is *OMITted then the procedure behaves as if \
40 | pos
would have been passed with value *on
. This can be used to position \
41 | the cursor and read the next key/item pair in one call without having \
42 | to provide an indicator field.
\
43 | ● This procedure disposes key1
and key2
automatically, unless \
44 | key1
/key2
is a manually disposed map, or a value/map contained \
45 | in a map.\
46 |
❘Create a new time value
\ 5 | <<pointer\ 9 |
\ 6 | value time(*iso.) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new time value.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a time/timestamp to an RPG time value
\ 5 | <<time(*iso.)\ 9 |
\ 6 | value pointer value
\ 7 | default time(*iso.) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG time
from value
, which must be a time or timestamp.
\
11 | ● If value
is *null
then return *loval
, or default
\
12 | when passed. If value
is not compatible escape message RM00011 (value not \
13 | compatible) is sent.
\
14 | ● A timestamp is converted to a time using BIF %time.\
15 |
❘Same as rm_t_, and dispose the time/timestamp
\ 5 | <<time(*iso.)\ 9 |
\ 6 | value pointer value
\ 7 | default time(*iso.) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_t_
. Additionally, value
is immediately disposed.\
11 |
❘Return user data
rm_user_data\ 5 |
\ 6 | <<int(10)\ 9 |
\ 7 | obj pointer value
\ 8 |
\
10 | ● Return the user data of obj
, which must be a map or a value.
\
11 | ● Return 0
if there is no user data.
\
12 | ● See rm_
.\
13 |
❘Create a new vector, automatically disposed
\ 5 | <<pointer\ 10 |
\ 6 | i001 pointer value options(*nopass)
\ 7 | ...
\ 8 | i100 pointer value options(*nopass)
\ 9 |
\
11 | ● Create a vector, i.e. same as rm_m
except that the keys can be only \
12 | integer values and two vectors are compared in a special way (see rm_cmp
). \
13 | E.g. rm_v(rm_d(d\'2017-01-01\'):rm_i(10))
and rm_v(rm_d(d\'2017-01-01\'))
are \
14 | considered equal.
\
15 | ● The parameters of this procedure to immediately populate the vector only \
16 | accept items. The keys are automatically generated. The first item is inserted \
17 | with key rm_i(1)
, the second with key rm_i(2)
, etc.
\
18 | ● A vector represents a simple sequence of items, and is specially useful as \
19 | a (partial) composite key.\
20 |
❘Create a new pointer value
\ 5 | <<pointer\ 9 |
\ 6 | value pointer value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new pointer value.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a pointer to an RPG pointer value
\ 5 | <<pointer\ 9 |
\ 6 | value pointer value
\ 7 | default pointer value options(*nopass)
\ 8 |
\
10 | ● Return an RPG pointer
from value
, which must be a pointer.
\
11 | ● If value
is *null
then return *null
, or default
\
12 | when passed. If value
is not compatible escape message RM00011 (value not \
13 | compatible) is sent.
\
14 |
❘Same as rm_x_, and dispose the pointer
\ 5 | <<pointer\ 9 |
\ 6 | value pointer value
\ 7 | default pointer value options(*nopass)
\ 8 |
\
10 | ● Same as rm_x_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new procedure pointer value
\ 5 | <<pointer\ 9 |
\ 6 | value pointer(*proc) value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new procedure pointer value.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a procedure pointer to an RPG procedure pointer value
\ 5 | <<pointer(*proc)\ 9 |
\ 6 | value pointer value
\ 7 | default pointer(*proc) value options(*nopass)
\ 8 |
\
10 | ● Return an RPG pointer(*proc)
from value
, which must be a procedure pointer.
\
11 | ● If value
is *null
then return *null
, or default
\
12 | when passed. If value
is not compatible escape message RM00011 (value not \
13 | compatible) is sent.\
14 |
❘Same as rm_xp_, and dispose the proc. pointer
\ 5 | <<pointer(*proc)\ 9 |
\ 6 | value pointer value
\ 7 | default pointer(*proc) value options(*nopass)
\ 8 |
\
10 | ● Same as rm_xp_
. Additionally, value
is immediately disposed.\
11 |
❘Create a new timestamp value
\ 5 | <<pointer\ 9 |
\ 6 | value timestamp value
\ 7 | opt int(10) value options(*nopass)
\ 8 |
\
10 | ● Create a new timestamp value.
\
11 | ● Pass opt
to set special property or user data (see rm_
).\
12 |
❘Convert a date/timestamp to an RPG timestamp value
\ 5 | <<timestamp\ 9 |
\ 6 | value pointer value
\ 7 | default timestamp value options(*nopass)
\ 8 |
\
10 | ● Return an RPG timestamp
from value
, which must be a date or timestamp.
\
11 | ● If value
is *null
then return *loval
, or default
\
12 | when passed. If value
is not compatible escape message RM00011 (value not \
13 | compatible) is sent.
\
14 | ● A date is converted to a timestamp using BIF %timestamp.\
15 |
❘Same as rm_z_, and dispose the date/timestamp
\ 5 | <<timestamp\ 9 |
\ 6 | value pointer value
\ 7 | default timestamp value options(*nopass)
\ 8 |
\
10 | ● Same as rm_z_
. Additionally, value
is immediately disposed.\
11 |
\
6 | The order of a key in a map is determined by the compare function of the map. By default this \
7 | is rm_cmp
. This compare function can be replaced by another \
8 | (but only when the map is empty). See rm_scf
.\
9 |
\
11 | The sort order, when values and maps are compared with each other, is influenced by whether the compared \
12 | maps and/or values have the "reversed order" and/or "case insensitive order" property (see rm_
) \
13 | and/or whether character data or strings are sorted using an alternate sort sequence (rm_aa
, rm_sa
).\
14 |
\
16 | Procedure rm_cmp
compares values and maps and uses the alternate \
17 | sort sequence, and/or the "case insensitive order" property to determine the order, if applicable. \
18 | However, when rm_cmp
is replaced, "alternate sort sequence" and the \
19 | "case insensitive order" property are not guaranteed to function as expected anymore, depending on the \
20 | logic of the new compare function. The "reversed order property" will always function as expected; it can \
21 | can not be ignored or altered by a new compare function.\
22 |
\
6 | RpgMap is not threadsafe. That means that when multiple threads are active in a job that uses RpgMap, care should \
7 | be taken that no two threads execute any RpgMap procedure within the same activation group at the same time. \
8 | This can be done using synchronization constructs such as locks, sempahores or mutexes. One could also simply specify \
9 | control-options keyword thread(*serialize)
for an RPG module, and make sure that all access to RpgMap is \
10 | done through that module. This ensures that only one thread accesses RpgMap at any moment in time. This solution has \
11 | a coarse granularity. It hinders performance when many threads are waiting and there is a greater risk for deadlocks. \
12 | However, for most practical purposes using thread(*serialize)
would be good enough.\
13 |
\
6 | Install library RPGMAP.
\
7 | And add the following to your RPG source:
\
8 |
\ 10 | bnddir(\'RPGMAP/RPGMAP\')\ 13 |
\ 11 | /include RPGMAP/INCLUDERPG,RPGMAP\ 12 |
\ 14 | The IBM i version used must be at least 7.2.\ 15 |
\ 16 | \ 17 | '); 18 | -------------------------------------------------------------------------------- /docs/content/vectors.js: -------------------------------------------------------------------------------- 1 | document.write('\ 2 | \ 3 |\
6 | A vector is a special automatically disposed map, created with rm_v
. \
7 | It\'s mainly used for representing a list or a sequence, particularly a (partial) composite key. \
8 | A composite key is a key that is not one value, but a sequence of 1 or more values. See example 2.\
9 |
\ 11 | The keys of a vector must always be integers.\ 12 |
\ 13 |\
14 | The expression rm_v(rm_a(\'a\'):rm_a(\'b\'))
creates a vector, i.e. a map, with keys 1
\
15 | and 2
and items \'a\'
and \'b\'
. Only the items are specified. \
16 | The keys are automatically generated; the first item gets key rm_i(1)
, the second item gets key rm_i(2)
, etc.\
17 |
\
19 | When two vectors are compared the comparison is done differently than when two normal maps or a map and a vector \
20 | are compared. The keys are not compared, only the items (in key order). But unlike with maps, when the two vectors \
21 | have a different number of key/item pairs then only the first n key/item pairs from both vectors are relevant. \
22 | The extra key/item pairs from one of the two vectors are ignored. For example, vectors rm_v(rm_i(1):rm_i(2))
\
23 | and rm_v(rm_i(1))
are considered equal because only the first item of each vector are relevant. See \
24 | rm_cmp
for details.\
25 |
\
27 | Up to 100 key/item pairs can be immediately inserted with procedure rm_v
. \
28 | Only the items need to be specified: the keys are implied (rm_i(1)
, rm_i(2)
, ...). \
29 | So rm_v
is often used to represent a simple "list" or "sequence".\
30 |