-
Notifications
You must be signed in to change notification settings - Fork 15
/
cl_abap_conv_in_ce.clas.abap
134 lines (114 loc) · 3.4 KB
/
cl_abap_conv_in_ce.clas.abap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
CLASS cl_abap_conv_in_ce DEFINITION PUBLIC.
PUBLIC SECTION.
CLASS-METHODS
create
IMPORTING
encoding TYPE abap_encoding DEFAULT 'UTF-8'
input TYPE xstring OPTIONAL
replacement TYPE char1 DEFAULT '#'
ignore_cerr TYPE abap_bool DEFAULT abap_false
endian TYPE char1 OPTIONAL
RETURNING
VALUE(ret) TYPE REF TO cl_abap_conv_in_ce.
CLASS-METHODS
uccpi
IMPORTING
value TYPE i
RETURNING
VALUE(ret) TYPE string.
TYPES ty_char2 TYPE c LENGTH 2.
CLASS-METHODS uccp
IMPORTING
uccp TYPE simple
RETURNING
VALUE(char) TYPE ty_char2.
METHODS convert
IMPORTING
input TYPE xsequence
n TYPE i OPTIONAL
EXPORTING
data TYPE string.
METHODS read
IMPORTING
n TYPE i OPTIONAL
EXPORTING
data TYPE string.
PRIVATE SECTION.
DATA mv_input TYPE xstring.
DATA mv_js_encoding TYPE string.
DATA mv_ignore_cerr TYPE abap_bool.
ENDCLASS.
CLASS cl_abap_conv_in_ce IMPLEMENTATION.
METHOD create.
ASSERT replacement = '#'. " todo
ASSERT endian IS INITIAL. " todo
CREATE OBJECT ret.
CASE encoding.
WHEN 'UTF-16'.
ret->mv_js_encoding = 'utf-16le'.
WHEN 'UTF-8'.
ret->mv_js_encoding = 'utf8'.
WHEN '4103'.
ret->mv_js_encoding = 'utf-16le'.
WHEN OTHERS.
ASSERT 1 = 'not supported'.
ENDCASE.
ret->mv_input = input.
ret->mv_ignore_cerr = ignore_cerr.
ENDMETHOD.
METHOD uccp.
DATA int TYPE i.
DATA hex TYPE x LENGTH 2.
hex = uccp.
int = hex.
TRY.
char = uccpi( int ).
CATCH cx_sy_conversion_codepage.
* todo, hmm
ENDTRY.
ENDMETHOD.
METHOD uccpi.
DATA lv_hex TYPE x LENGTH 2.
DATA lo_in TYPE REF TO cl_abap_conv_in_ce.
lv_hex = value.
" switch to little endian
CONCATENATE lv_hex+1(1) lv_hex(1) INTO lv_hex IN BYTE MODE.
lo_in = create( encoding = '4103' ).
lo_in->convert(
EXPORTING
input = lv_hex
IMPORTING
data = ret ).
ENDMETHOD.
METHOD convert.
DATA lv_error TYPE abap_bool.
ASSERT mv_js_encoding IS NOT INITIAL.
WRITE '@KERNEL let buf = Buffer.from(input.get(), "hex");'.
" Try TextDecoder first, if it runs in browser,
WRITE '@KERNEL const decoder = TextDecoder || await import("util").TextDecoder;'.
* https://stackoverflow.com/questions/62334608/textdecoder-prototype-ignorebom-not-working-as-expected
WRITE '@KERNEL const td = new decoder(this.mv_js_encoding.get(), {fatal: this.mv_ignore_cerr.get() !== "X", ignoreBOM: true});'.
WRITE '@KERNEL try {'.
" WRITE '@KERNEL console.dir(buf);'.
WRITE '@KERNEL data.set(td.decode(buf));'.
" WRITE '@KERNEL console.dir(td.decode(buf).charCodeAt( 0 ));'.
WRITE '@KERNEL } catch (e) {'.
* WRITE '@KERNEL console.dir(e);'.
* WRITE '@KERNEL console.dir(this.mv_js_encoding.get());'.
lv_error = abap_true.
WRITE '@KERNEL }'.
IF lv_error = abap_true.
RAISE EXCEPTION TYPE cx_sy_conversion_codepage.
ENDIF.
* old WRITE '@KERNEL let result = buf.toString(this.mv_js_encoding.get());'.
* old WRITE '@KERNEL data.set(result);'.
ENDMETHOD.
METHOD read.
convert(
EXPORTING
input = mv_input
n = n
IMPORTING
data = data ).
ENDMETHOD.
ENDCLASS.