konto_check_ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,614 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of konto_check_ruby, a Ruby port of the C library
4
+ # konto_check, Copyright (C) 2002-2023 Michael Plugge <konto_check@yahoo.com>.
5
+ # Ruby port Copyright (C) 2026 tickettoaster GmbH <https://tickettoaster.de>.
6
+ #
7
+ # konto_check_ruby is free software; you can redistribute it and/or modify it
8
+ # under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation; either version 2.1 of the License, or (at
10
+ # your option) any later version. It is distributed WITHOUT ANY WARRANTY; see
11
+ # the file LICENSE for details.
12
+
13
+ require_relative "engine"
14
+
15
+ # KontoCheckRaw is the interface of the C extension of the original
16
+ # konto_check gem, implemented in pure Ruby on top of KontoCheckRuby::Engine.
17
+ # Function names, parameter handling and return values (mostly Arrays of
18
+ # [value, status]) follow the C extension konto_check_raw_ruby.c; the module
19
+ # KontoCheck (see konto_check.rb) offers the more Ruby-like interface.
20
+ #
21
+ # Return code constants (OK, FALSE, INVALID_BLZ, ...) are available as
22
+ # KontoCheckRaw::OK etc.
23
+ module KontoCheckRaw
24
+ include KontoCheckRuby
25
+
26
+ UNIQ_DEFAULT = 2
27
+ DEFAULT_INIT_LEVEL = KontoCheckRuby::Engine::DEFAULT_INIT_LEVEL
28
+
29
+ class << self
30
+ # The engine behind the module functions (KontoCheckRuby.engine by default)
31
+ def engine
32
+ KontoCheckRuby.engine
33
+ end
34
+
35
+ # ---------------------------------------------------------------- init
36
+
37
+ # init([p1 [,p2 [,set]]]) - p1/p2 are the LUT file name (String) and the
38
+ # init level (Integer) in any order. Raises RuntimeError on errors.
39
+ def init(*args)
40
+ lut_name = nil
41
+ level = DEFAULT_INIT_LEVEL
42
+ set = 0
43
+ unless args.empty? || args[0].nil?
44
+ a1, a2, a3 = args
45
+ t1 = arg_type(a1)
46
+ t2 = arg_type(a2)
47
+ raise TypeError, "wrong type for filename or init level" unless t1 + t2 == 3 || (t1 == 2 && a2.nil?)
48
+ if t1 == 1
49
+ level = a1.to_i
50
+ lut_name = a2
51
+ else
52
+ lut_name = a1
53
+ level = a2.to_i unless a2.nil?
54
+ end
55
+ set = a3.to_i unless a3.nil?
56
+ end
57
+ retval = engine.init(lut_name, level, set)
58
+ runtime_error(retval) unless retval > 0 || partial_ok?(retval)
59
+ retval
60
+ end
61
+
62
+ def current_lutfile_name
63
+ engine.current_lutfile_name
64
+ end
65
+
66
+ def free
67
+ engine.free
68
+ true
69
+ end
70
+
71
+ def load_bank_data(_path)
72
+ raise RuntimeError, "Perhaps you used the old interface of konto_check.\n" \
73
+ "Use KontoCheck::init() to initialize the library\n" \
74
+ "and check the order of function arguments for konto_test(blz,kto)"
75
+ end
76
+
77
+ # ------------------------------------------------------------- checks
78
+
79
+ def konto_check(*args)
80
+ blz, kto = params_blz_kto(args)
81
+ if (blz.start_with?("0") || blz.length != 8) && engine.lut_blz(kto[2..].to_s, 0) == OK
82
+ raise RuntimeError, "It seems that you use the old interface of konto_check?\n" \
83
+ "Please check the order of function arguments for konto_test(); should be (blz,kto)"
84
+ end
85
+ retval = engine.kto_check_blz(blz, kto)
86
+ runtime_error(retval) if retval == LUT2_NOT_INITIALIZED || retval == MISSING_PARAMETER
87
+ retval
88
+ end
89
+
90
+ def konto_check_pz(*args)
91
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 2..3)" unless (2..3).cover?(args.size)
92
+ pz = args[0].is_a?(Numeric) ? format("%02d", args[0].to_i) : str_arg(args[0], "Unable to convert given value.")
93
+ kto = kto_arg(args[1])
94
+ blz = args[2].nil? ? nil : (args[2].is_a?(Numeric) ? args[2].to_i.to_s : str_arg(args[2], "Unable to convert given blz."))
95
+ retval = engine.kto_check_pz(pz, kto, blz)
96
+ runtime_error(retval) if retval == LUT2_NOT_INITIALIZED || retval == MISSING_PARAMETER
97
+ retval
98
+ end
99
+
100
+ def konto_check_regel(*args)
101
+ blz, kto = params_blz_kto(args)
102
+ retval = engine.kto_check_regel(blz, kto)
103
+ runtime_error(retval) if retval == LUT2_NOT_INITIALIZED || retval == MISSING_PARAMETER
104
+ retval
105
+ end
106
+
107
+ # [retval, blz2, kto2, bic, regel, regel_version, methode, pz_methode, pz, pz_pos]
108
+ def konto_check_regel_dbg(*args)
109
+ blz, kto = params_blz_kto(args)
110
+ retval, blz2, kto2, bic, regel, rv = engine.kto_check_regel_dbg(blz, kto)
111
+ runtime_error(retval) if retval == LUT2_NOT_INITIALIZED || retval == MISSING_PARAMETER
112
+ [retval, blz2.to_s, kto2.to_s, bic.to_s, regel / 100, regel % 100, rv.methode, rv.pz_methode, rv.pz, rv.pz_pos]
113
+ end
114
+
115
+ def pz_aenderungen_enable(*args)
116
+ mode = args[0].nil? ? -1 : int_arg(args[0])
117
+ engine.pz_aenderungen_enable(mode)
118
+ end
119
+
120
+ # ---------------------------------------------------------- bank data
121
+
122
+ def bank_valid(*args)
123
+ blz, filiale = params_blz_filiale(args)
124
+ retval = engine.lut_blz(blz, filiale)
125
+ runtime_error(retval) if retval == LUT2_BLZ_NOT_INITIALIZED
126
+ retval
127
+ end
128
+
129
+ # [count, retval]
130
+ def bank_filialen(*args)
131
+ blz, = params_blz_filiale(args)
132
+ cnt, retval = engine.lut_filialen(blz)
133
+ runtime_error(retval) if retval == LUT2_BLZ_NOT_INITIALIZED || retval == LUT2_FILIALEN_NOT_INITIALIZED
134
+ [retval <= 0 ? nil : cnt, retval]
135
+ end
136
+
137
+ # [retval, cnt, name, name_kurz, plz, ort, pan, bic, pz, nr, aenderung, loeschung, nachfolge_blz]
138
+ def bank_alles(*args)
139
+ blz, filiale = params_blz_filiale(args)
140
+ m = engine.lut_multiple(blz)
141
+ retval = m[:retval]
142
+ runtime_error(retval) if retval == LUT2_BLZ_NOT_INITIALIZED
143
+ return LUT2_INDEX_OUT_OF_RANGE if retval > 0 && (filiale < 0 || (m[:cnt] && filiale >= m[:cnt]))
144
+ return [retval, nil] if retval <= 0 && retval != LUT2_PARTIAL_OK
145
+ f = ->(key) { m[key] ? m[key][filiale] : nil }
146
+ sv = ->(v) { v.nil? || v.to_s.empty? ? nil : engine.encode_out(v) }
147
+ iv = ->(v) { v.nil? || v < 0 ? nil : v }
148
+ [retval, iv.call(m[:cnt]), sv.call(f.call(:name)), sv.call(f.call(:name_kurz)), iv.call(f.call(:plz)),
149
+ sv.call(f.call(:ort)), iv.call(f.call(:pan)), f.call(:bic), iv.call(m[:pz]), iv.call(f.call(:nr)),
150
+ f.call(:aenderung), f.call(:loeschung), iv.call(f.call(:nachfolge_blz))]
151
+ end
152
+
153
+ def bank_name(*args)
154
+ field_result(:lut_name, args, LUT2_NAME_NOT_INITIALIZED, encode: true)
155
+ end
156
+
157
+ def bank_name_kurz(*args)
158
+ field_result(:lut_name_kurz, args, LUT2_NAME_KURZ_NOT_INITIALIZED, encode: true)
159
+ end
160
+
161
+ def bank_ort(*args)
162
+ field_result(:lut_ort, args, LUT2_ORT_NOT_INITIALIZED, encode: true)
163
+ end
164
+
165
+ def bank_plz(*args)
166
+ field_result(:lut_plz, args, LUT2_PLZ_NOT_INITIALIZED)
167
+ end
168
+
169
+ def bank_pan(*args)
170
+ field_result(:lut_pan, args, LUT2_PAN_NOT_INITIALIZED)
171
+ end
172
+
173
+ def bank_bic(*args)
174
+ field_result(:lut_bic, args, LUT2_BIC_NOT_INITIALIZED)
175
+ end
176
+
177
+ def bank_nr(*args)
178
+ field_result(:lut_nr, args, LUT2_NR_NOT_INITIALIZED)
179
+ end
180
+
181
+ def bank_pz(*args)
182
+ blz, = params_blz_filiale(args)
183
+ pz, retval = engine.lut_pz(blz, 0)
184
+ runtime_error(retval) if retval == LUT2_BLZ_NOT_INITIALIZED || retval == LUT2_PZ_NOT_INITIALIZED
185
+ [retval <= 0 ? nil : pz, retval]
186
+ end
187
+
188
+ def bank_aenderung(*args)
189
+ field_result(:lut_aenderung, args, LUT2_AENDERUNG_NOT_INITIALIZED)
190
+ end
191
+
192
+ def bank_loeschung(*args)
193
+ field_result(:lut_loeschung, args, LUT2_LOESCHUNG_NOT_INITIALIZED)
194
+ end
195
+
196
+ def bank_nachfolge_blz(*args)
197
+ field_result(:lut_nachfolge_blz, args, LUT2_NACHFOLGE_BLZ_NOT_INITIALIZED)
198
+ end
199
+
200
+ # -------------------------------------------------- bic_* / biq_* / iban_*
201
+
202
+ # bic_info(bic [,mode]) -> [start_idx, cnt, retval]
203
+ def bic_info(*args)
204
+ bic = bic_arg(args[0], 11)
205
+ mode = args[1].nil? ? 0 : int_arg(args[1])
206
+ retval, cnt, start_idx = engine.bic_info(bic, mode)
207
+ runtime_error(retval) if retval < 0 && retval != KEY_NOT_FOUND
208
+ [retval < 0 ? nil : start_idx, cnt, retval]
209
+ end
210
+
211
+ %i[name name_kurz plz ort pan bic nr pz aenderung loeschung nachfolge_blz].each do |field|
212
+ define_method(:"bic_#{field}") do |*args|
213
+ bic = bic_arg(args[0], 11)
214
+ mode = args[1].nil? ? 0 : int_arg(args[1])
215
+ filiale = args[2].nil? ? 0 : int_arg(args[2])
216
+ value, retval = engine.bic_field(field, bic, mode, filiale)
217
+ runtime_error(retval) if retval < 0 && retval != KEY_NOT_FOUND
218
+ [retval <= 0 ? nil : out_value(field, value), retval]
219
+ end
220
+
221
+ define_method(:"biq_#{field}") do |*args|
222
+ idx = int_arg(args[0])
223
+ value, retval = engine.biq_field(field, idx)
224
+ runtime_error(retval) if retval < 0 && retval != KEY_NOT_FOUND
225
+ [retval <= 0 ? nil : out_value(field, value), retval]
226
+ end
227
+
228
+ define_method(:"iban_#{field}") do |*args|
229
+ iban = bic_arg(args[0], 22)
230
+ filiale = args[1].nil? ? 0 : int_arg(args[1])
231
+ unless iban[0, 2].to_s.casecmp("DE").zero?
232
+ return [nil, IBAN_ONLY_GERMAN]
233
+ end
234
+ return [nil, INVALID_IBAN_LENGTH] unless iban.length == 22
235
+ blz = iban[4, 8]
236
+ value, retval = case field
237
+ when :pz then engine.lut_pz(blz, filiale)
238
+ else engine.public_send(:"lut_#{field}", blz, filiale)
239
+ end
240
+ runtime_error(retval) if retval == LUT2_BLZ_NOT_INITIALIZED
241
+ [retval <= 0 ? nil : out_value(field, value), retval]
242
+ end
243
+ end
244
+
245
+ # ------------------------------------------------------------ LUT file
246
+
247
+ # [dump, retval]
248
+ def dump_lutfile(*args)
249
+ name = str_arg(args[0], "wrong type for filename")
250
+ retval, dump = engine.dump_lutfile(name)
251
+ [retval <= 0 ? nil : dump, retval]
252
+ end
253
+
254
+ # lut_blocks([mode]) -> [retval, filename, blocks_ok, blocks_failed]
255
+ def lut_blocks(*args)
256
+ mode = args[0].nil? ? 1 : int_arg(args[0], "lut_blocks() requires an int parameter")
257
+ retval, filename, ok, fail = engine.lut_blocks(mode)
258
+ return [retval, nil, nil, nil] if retval == LUT2_NOT_INITIALIZED
259
+ [retval, filename, ok, fail]
260
+ end
261
+
262
+ def lut_blocks1
263
+ engine.lut_blocks(0)[0]
264
+ end
265
+
266
+ # lut_info([lutfile]) -> [retval, valid1, valid2, info1, info2]
267
+ def lut_info(*args)
268
+ name = args[0].nil? ? nil : str_arg(args[0], "wrong type for filename")
269
+ retval, info1, info2, valid1, valid2 = engine.lut_info(name)
270
+ runtime_error(retval) if retval < 0
271
+ [retval, valid1, valid2, info1, info2]
272
+ end
273
+
274
+ def keep_raw_data(_mode)
275
+ true
276
+ end
277
+
278
+ def encoding(*args)
279
+ engine.encoding(enc_mode(args[0]))
280
+ end
281
+
282
+ def encoding_str(*args)
283
+ engine.encoding_str(enc_mode(args[0]))
284
+ end
285
+
286
+ def retval2txt(retval) = engine.retval2txt(retval.to_i)
287
+ def retval2iso(retval) = engine.retval2iso(retval.to_i)
288
+ def retval2txt_short(retval) = engine.retval2txt_short(retval.to_i)
289
+ def retval2dos(retval) = engine.retval2dos(retval.to_i)
290
+ def retval2html(retval) = engine.retval2html(retval.to_i)
291
+ def retval2utf8(retval) = engine.retval2utf8(retval.to_i)
292
+
293
+ # generate_lutfile(inputfile, outputfile [,user_info [,gueltigkeit [,felder [,filialen [,set [,iban_blacklist]]]]]])
294
+ def generate_lutfile(*args)
295
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 2..8)" unless (2..8).cover?(args.size)
296
+ input = str_arg(args[0], "Unable to convert given input filename.")
297
+ output = str_arg(args[1], "Unable to convert given output filename.")
298
+ user_info = args[2].nil? ? "" : str_arg(args[2], "Unable to convert given user_info string.")
299
+ gueltigkeit = args[3].nil? ? nil : str_arg(args[3], "Unable to convert given gueltigkeit string.")
300
+ felder = args[4].nil? ? 9 : args[4].to_i
301
+ filialen = args[5].nil? ? 0 : args[5].to_i
302
+ set = args[6].nil? ? 0 : args[6].to_i
303
+ retval = engine.generate_lutfile(input, output, user_info, gueltigkeit, felder, filialen, set)
304
+ runtime_error(retval) if retval < 0
305
+ if args[7] && !args[7].to_s.empty?
306
+ KontoCheckRuby::LutFile.write_iban_blacklist(args[7].to_s, output, set)
307
+ end
308
+ retval
309
+ end
310
+
311
+ def rebuild_blzfile(*args)
312
+ input = str_arg(args[0], "Unable to convert given input filename.")
313
+ output = str_arg(args[1], "Unable to convert given output filename.")
314
+ set = args[2].nil? ? 1 : args[2].to_i
315
+ engine.rebuild_blzfile(input, output, set)
316
+ end
317
+
318
+ # ----------------------------------------------------------- IBAN etc.
319
+
320
+ def ci_check(ci)
321
+ return INVALID_PARAMETER_TYPE unless ci.is_a?(String)
322
+ engine.ci_check(ci[0, 35])
323
+ end
324
+
325
+ # [retval, cnt]
326
+ def bic_check(bic)
327
+ return INVALID_PARAMETER_TYPE unless bic.is_a?(String)
328
+ engine.bic_check(bic[0, 11])
329
+ end
330
+
331
+ # [retval, retval_kc]
332
+ def iban_check(*args)
333
+ iban = str_arg(args[0], "Unable to convert given value.")[0, 128]
334
+ engine.iban_check(iban)
335
+ end
336
+
337
+ # [bic, retval, blz, kto]
338
+ def iban2bic(*args)
339
+ iban = str_arg(args[0], "Unable to convert given value.")[0, 128]
340
+ bic, retval, blz, kto = engine.iban2bic(iban)
341
+ [bic.nil? || bic.empty? ? nil : bic, retval, blz.nil? || blz.empty? ? nil : blz, kto.nil? || kto.empty? ? nil : kto]
342
+ end
343
+
344
+ # iban_gen(blz, kto) -> [iban, iban_papier, retval, bic, blz2, kto2, regel]
345
+ def iban_gen(*args)
346
+ blz, kto = params_blz_kto(args)
347
+ retval, papier, bic, blz2, kto2 = engine.iban_bic_gen(blz, kto)
348
+ if retval > 0
349
+ regel = engine.lut_iban_regel(blz, 0)[0] / 100
350
+ [papier.delete(" "), papier, retval, bic.to_s, blz2, kto2, regel]
351
+ else
352
+ [nil, nil, retval, nil, nil, nil, -1]
353
+ end
354
+ end
355
+
356
+ # [ipi, ipi_papier, retval]
357
+ def ipi_gen(*args)
358
+ zweck = str_arg(args[0], "Unable to convert given value.")[0, 24]
359
+ retval, dst, papier = engine.ipi_gen(zweck)
360
+ retval == OK ? [dst, papier, retval] : [nil, nil, retval]
361
+ end
362
+
363
+ def ipi_check(*args)
364
+ zweck = str_arg(args[0], "Unable to convert given value.")[0, 128]
365
+ engine.ipi_check(zweck)
366
+ end
367
+
368
+ # ------------------------------------------------------------- search
369
+
370
+ # bank_suche_xxx(value [,uniq [,sort]]) -> [values, blz, zweigstellen, retval, anzahl]
371
+ def bank_suche_bic(*args) = suche_str(:lut_suche_bic, :bic, args)
372
+ def bank_suche_namen(*args) = suche_str(:lut_suche_namen, :name, args)
373
+ def bank_suche_namen_kurz(*args) = suche_str(:lut_suche_namen_kurz, :name_kurz, args)
374
+ def bank_suche_ort(*args) = suche_str(:lut_suche_ort, :ort, args)
375
+
376
+ def bank_suche_blz(*args) = suche_int(:lut_suche_blz, :blz, args)
377
+ def bank_suche_plz(*args) = suche_int(:lut_suche_plz, :plz, args)
378
+ def bank_suche_pz(*args) = suche_int(:lut_suche_pz, :pz, args)
379
+ def bank_suche_regel(*args) = suche_int(:lut_suche_regel, :regel, args)
380
+
381
+ # bank_suche_volltext(word [,uniq [,sort]]) -> [words, blz, zweigstellen, retval, anzahl]
382
+ def bank_suche_volltext(*args)
383
+ word, _cmd, uniq = params_suche(args)
384
+ retval, hits, words = engine.lut_suche_volltext(word)
385
+ return [nil, nil, nil, retval, 0] if retval == KEY_NOT_FOUND
386
+ runtime_error(retval) if retval < 0
387
+ blz, zw = shape_hits(hits, uniq)
388
+ [words.map { |w| engine.encode_out(w) }, blz, zw, retval, blz.size]
389
+ end
390
+
391
+ # bank_suche_multiple(such_text [,such_cmd [,uniq]]) -> [nil, blz, zweigstellen, retval, anzahl]
392
+ def bank_suche_multiple(*args)
393
+ text, cmd, uniq = params_suche(args, maxlen: 1280)
394
+ retval, pairs = engine.lut_suche_multiple(text, uniq > 1, cmd)
395
+ return [nil, nil, nil, retval, 0] if retval == KEY_NOT_FOUND || pairs.empty?
396
+ runtime_error(retval) if retval < 0
397
+ [nil, pairs.map(&:first), pairs.map(&:last), retval, pairs.size]
398
+ end
399
+
400
+ # ------------------------------------------------------- SCL directory
401
+
402
+ # The SCL directory (SEPA Clearer Verzeichnis) is not supported by the
403
+ # Ruby port; the functions return the corresponding error codes.
404
+ def scl_init(*_args) = NO_SCL_BLOCKS_LOADED
405
+ def scl_multi(*_args) = [NO_SCL_BLOCKS_LOADED, nil, nil, nil]
406
+ def scl_multi_blz(*_args) = [NO_SCL_BLOCKS_LOADED, nil, nil, nil]
407
+ %w[sct sdd cor1 b2b scc].each do |flag|
408
+ define_method(:"scl_#{flag}") { |*_args| [nil, NO_SCL_BLOCKS_LOADED] }
409
+ define_method(:"scl_#{flag}_blz") { |*_args| [nil, NO_SCL_BLOCKS_LOADED, nil] }
410
+ end
411
+
412
+ def version(*args)
413
+ engine.version(args[0].nil? ? 0 : args[0].to_i)
414
+ end
415
+
416
+ private
417
+
418
+ def partial_ok?(retval)
419
+ [LUT2_PARTIAL_OK, LUT2_NO_LONGER_VALID_PARTIAL_OK, LUT2_NOT_YET_VALID_PARTIAL_OK, LUT1_SET_LOADED].include?(retval)
420
+ end
421
+
422
+ def runtime_error(retval)
423
+ raise RuntimeError, "KontoCheck::#{engine.retval2txt_short(retval)}, #{engine.retval2txt(retval)}"
424
+ end
425
+
426
+ def arg_type(v)
427
+ case v
428
+ when Numeric then 1
429
+ when String then 2
430
+ else 0
431
+ end
432
+ end
433
+
434
+ def str_arg(v, msg)
435
+ raise TypeError, msg unless v.is_a?(String)
436
+ v
437
+ end
438
+
439
+ def int_arg(v, msg = "Unable to convert given value to int")
440
+ raise TypeError, msg unless v.is_a?(Numeric)
441
+ v.to_i
442
+ end
443
+
444
+ def bic_arg(v, maxlen)
445
+ raise TypeError, "First parameter must be string." unless v.is_a?(String)
446
+ v[0, maxlen]
447
+ end
448
+
449
+ def blz_arg(v)
450
+ case v
451
+ when String then v[0, 9]
452
+ when Numeric then format("%08d", v.to_i)
453
+ else raise TypeError, "Unable to convert given blz."
454
+ end
455
+ end
456
+
457
+ def kto_arg(v)
458
+ case v
459
+ when String then v[0, 15]
460
+ when Numeric then format("%010d", v.to_i)
461
+ else raise TypeError, "Unable to convert given kto."
462
+ end
463
+ end
464
+
465
+ def params_blz_kto(args)
466
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 2)" unless args.size == 2
467
+ [blz_arg(args[0]), kto_arg(args[1])]
468
+ end
469
+
470
+ def params_blz_filiale(args)
471
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1..2)" unless (1..2).cover?(args.size)
472
+ [blz_arg(args[0]), args[1].nil? ? 0 : args[1].to_i]
473
+ end
474
+
475
+ def field_result(meth, args, error, encode: false)
476
+ blz, filiale = params_blz_filiale(args)
477
+ value, retval = engine.public_send(meth, blz, filiale)
478
+ runtime_error(retval) if retval == LUT2_BLZ_NOT_INITIALIZED || retval == error
479
+ value = engine.encode_out(value) if encode && value
480
+ [retval <= 0 ? nil : value, retval]
481
+ end
482
+
483
+ def out_value(field, value)
484
+ %i[name name_kurz ort].include?(field) ? engine.encode_out(value) : value
485
+ end
486
+
487
+ def enc_mode(v)
488
+ return 0 if v.nil?
489
+ case v
490
+ when Numeric then v.to_i
491
+ when String
492
+ return v.to_i if v.to_i > 0
493
+ if v[0] =~ /[mM]/
494
+ case v[1]
495
+ when "i", "I" then 51
496
+ when "u", "U" then 52
497
+ when "h", "H" then 53
498
+ when "d", "D" then 54
499
+ else 52
500
+ end
501
+ else
502
+ v[0].to_s
503
+ end
504
+ else raise TypeError, "Unable to convert given value to int"
505
+ end
506
+ end
507
+
508
+ # search parameters: (value [, such_cmd/uniq [, uniq/sort [, sort]]])
509
+ def params_suche(args, maxlen: 128)
510
+ raise ArgumentError, "search value missing" if args.empty?
511
+ value = case args[0]
512
+ when String then args[0][0, maxlen]
513
+ when Numeric then args[0].to_s
514
+ else raise TypeError, "Unable to convert given value."
515
+ end
516
+ cmd = ""
517
+ uniq = -1
518
+ sort = -1
519
+ args[1..].to_a.each do |a|
520
+ case a
521
+ when nil then next
522
+ when String then cmd = a[0, 255]
523
+ when Numeric
524
+ if uniq < 0 then uniq = a.to_i else sort = a.to_i end
525
+ else raise TypeError, "Unable to convert given variable to integer or string"
526
+ end
527
+ end
528
+ uniq = if uniq > 0 then 2
529
+ elsif sort > 0 then 1
530
+ elsif uniq < 0 && sort < 0 then UNIQ_DEFAULT
531
+ else 0
532
+ end
533
+ [value, cmd, uniq]
534
+ end
535
+
536
+ # (a1 [, a2 [, uniq [, sort]]]) or ([a1, a2] [, uniq [, sort]]) or ("a1-a2" ...)
537
+ def params_suche_int(args)
538
+ raise ArgumentError, "search value missing" if args.empty?
539
+ a = args.dup
540
+ first = a.shift
541
+ a1 = a2 = 0
542
+ if first.is_a?(Array)
543
+ a1 = first[0].to_i
544
+ a2 = first[1].to_i
545
+ elsif first.is_a?(String) && first.include?("-")
546
+ p1, p2 = first.split("-", 2)
547
+ a1 = p1.to_i
548
+ a2 = p2.to_i
549
+ else
550
+ a1 = first.to_i
551
+ if a.first.is_a?(Numeric) || (a.first.is_a?(String) && a.first =~ /\A\s*\d+\s*\z/)
552
+ a2 = a.shift.to_i
553
+ end
554
+ end
555
+ uniq = -1
556
+ sort = -1
557
+ a.each do |x|
558
+ next if x.nil?
559
+ v = x.to_i
560
+ if uniq < 0 then uniq = v > 0 ? 2 : 0 else sort = v end
561
+ end
562
+ uniq = if uniq > 0 then 2
563
+ elsif sort > 0 then 1
564
+ elsif uniq < 0 && sort < 0 then UNIQ_DEFAULT
565
+ else 0
566
+ end
567
+ [a1, a2, uniq]
568
+ end
569
+
570
+ # sorts/uniques flat indexes like lut_suche_sort1(); returns [blz, zweigstellen, ordered hits]
571
+ def shape_hits(hits, uniq)
572
+ ordered = hits
573
+ if uniq > 0
574
+ ordered = hits.sort_by { |j| [engine.blz_f(j), engine.zweigstelle_f(j), j] }
575
+ if uniq > 1
576
+ seen = {}
577
+ ordered = ordered.reject { |j| b = engine.blz_f(j); seen.key?(b) ? true : (seen[b] = true; false) }
578
+ end
579
+ end
580
+ [ordered.map { |j| engine.blz_f(j) }, ordered.map { |j| engine.zweigstelle_f(j) }, ordered]
581
+ end
582
+
583
+ def suche_str(meth, field, args)
584
+ value, _cmd, uniq = params_suche(args)
585
+ retval, hits = engine.public_send(meth, value)
586
+ return [nil, nil, nil, retval, 0] if retval == KEY_NOT_FOUND
587
+ runtime_error(retval) if retval < 0
588
+ blz, zw, ordered = shape_hits(hits, uniq)
589
+ values = ordered.map { |j| out_value(field, engine.data.public_send(field)[j]) }
590
+ [values, blz, zw, retval, blz.size]
591
+ end
592
+
593
+ def suche_int(meth, field, args)
594
+ a1, a2, uniq = params_suche_int(args)
595
+ retval, hits = engine.public_send(meth, a1, a2)
596
+ return [nil, nil, nil, retval, 0] if retval == KEY_NOT_FOUND
597
+ runtime_error(retval) if retval < 0
598
+ blz, zw, ordered = shape_hits(hits, uniq)
599
+ values = case field
600
+ when :blz then blz
601
+ when :pz then ordered.map { |j| engine.pz_f(j) }
602
+ when :plz then ordered.map { |j| engine.data.plz[j] }
603
+ when :regel then ordered.map { |j| engine.data.iban_regel[j] / 100 }
604
+ end
605
+ [values, blz, zw, retval, blz.size]
606
+ end
607
+ end
608
+
609
+ # all return codes as constants of this module (KontoCheckRaw::OK ...)
610
+ KontoCheckRuby.constants.each do |c|
611
+ v = KontoCheckRuby.const_get(c)
612
+ const_set(c, v) if v.is_a?(Integer) && !const_defined?(c, false)
613
+ end
614
+ end