-
Notifications
You must be signed in to change notification settings - Fork 11
/
util.sfunc.tf
311 lines (280 loc) · 9.31 KB
/
util.sfunc.tf
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
; $Log: util.sfunc.tf,v $
; Revision 1.8 2002/09/08 17:26:37 mh14
; reval macht ein internes eval statt /eval /let
;
; Revision 1.7 2002/04/18 19:34:50 mh14
; /qsort,/qnsort von ken keys
;
; Revision 1.6 2001/11/28 11:02:55 mh14
; md5 als hash vorgesehen
;
; Revision 1.5 2001/09/09 19:09:42 mh14
; help_de.list
;
; Revision 1.4 2001/09/06 21:11:44 mh14
; Log eingefuegt
;
/set util_sfunc_tf_version $Id$
/set [email protected]
/set util_sfunc_tf_requires=
/set util_sfunc_tf_desc Stringfunktionen, Aufspalten, Hashcode, Sprintf
/set MAX_INT=2147483647
/addh info \
Spaltet Strings entsprechend der angegebenen Begrenzer auf.
/addh syn $[tokenize("begrenzer z.b. space Komma usw.","string")]
/addh return %T0 anzahl der aufspaltungen@{N}\
%Ti ite aufspaltung
/addh version 1.01
/addh tokenize mak
/def tokenize = \
/let param=%{2}%;\
/let token_praefix=%{3-T}%;\
/let counter=1%;\
/let off=$[strstr(param,{1})]%;\
/let delimlen=$[strlen({1})]%;\
/while (off!=-1) \
/set %{token_praefix}%counter=$[substr(param,0,off)]%;\
/let counter=$[counter+1]%;\
/let param=$[substr(param,off+delimlen)]%;\
/let toff=$[strstr(param,{1})]%;\
/while (toff==0)\
/let param=$[substr(param,delimlen)]%;\
/let toff=$[strstr(param,{1})]%;\
/done%;\
/let off=%toff%;\
/done%;\
/set %{token_praefix}%counter=%param%;\
/set %{token_praefix}0=%counter%;
/def ctokenize = \
/let param=%{2}%;\
/let token_praefix=%{3-T}%;\
/let counter=1%;\
/let off=$[strchr(param,{1})]%;\
/while (off!=-1) \
/set %{token_praefix}%counter=$[substr(param,0,off)]%;\
/let counter=$[counter+1]%;\
/let param=$[substr(param,off+1)]%;\
/let toff=$[strchr(param,{1})]%;\
/while (toff==0)\
/let param=$[substr(param,delimlen)]%;\
/let toff=$[strstr(param,{1})]%;\
/done%;\
/let off=%toff%;\
/done%;\
/set %{token_praefix}%counter=%param%;\
/set %{token_praefix}0=%counter%;
/addh info \
Ersetzt die nummerierten #i im uebergebenen String durch die i-ten Parameter, die sprintf uebergeben wurden.
/addh ex /test sprintf("#1 Bytes von #2 gelesen",100,"test.txt")
/addh syn /test sprintf("String",parameters,...)
/addh return String mit Ersetzungen
/addh sprintf func
/def sprintf = \
/let param=%;\
/test param:={1}%;\
/let count=1%;\
/shift%;\
/while ({#}>0) \
/test param:=replace(strcat("#",count),{1},param)%;\
/shift%;\
/test ++count%;\
/done%;\
/result param
/addh info \
Sucht den String2 ab der angegebenen Position im String1.
/addh syn strnstr(string1,off,string2)
/addh return den Offset von String2 vom Beginn von String1 oder -1 bei Fehler
/addh strnstr mak
/def strnstr = \
/let temp=$[strstr(substr({1},{2}),{3})] %;\
/return (temp==-1)?{temp}:(temp+{2})%;
/addh info \
Liefert den uebergebenen Text mit Grossbuchstaben am Anfang zurueck.
/addh capitalize mak
/def capitalize = \
/result strcat(toupper(substr({*},0,1)),substr({*},1))%;
/addh info \
Liefert einen Hashwert des uebergebenen Strings zurueck. Dieser wird gebildet, indem eine Verkettung aus Stringlaenge modulo 1000, sowie den ASCII Werten der folgenden Zeichen erzeugt wird. 1. Zeichen bei Position Stringlaenge modulo 100 (als Prozentwert dividiert durch 100) mal Stringlaenge (hier mod. 1000, ist aber nicht so wichtig). 2. Zeichen bei Stringlaenge (mod 1000) - Position1.@{N}\
Wenn der String weniger als 10 Zeichen beinhaltet, wird der Hashcode nach folgender Formel berechnet: x=0, x:=x*8+ascii(i), i=0..strlen
/addh syn /hash1 string, Returnwert per /result
/addh hash1 mak
/def hash = \
/let param=%*%;\
/let hash_len=$[strlen(param)]%;\
/let tmp=%;\
/if (hash_len>10) \
/let hash_hcount=$[mod(hash_len,1000)]%;\
/let hash_pcount=$[mod(hash_hcount,100)]%;\
/let hash_pos=$[(hash_len-1)*(hash_pcount)/100]%;\
/let hash_pos2=$[hash_len-1-hash_pos]%;\
/result replace(" ","0",pad(hash_hcount,3,ascii(substr(param,hash_pos,1)),3,ascii(substr(param,hash_pos2,1)),3))%;\
/else \
/let hash_hcount=0%;\
/while (--hash_len>-1) \
; problem overflow wird zu real zahl bei tf5
/let tmp=$[8*hash_hcount+ascii(param)]%;\
/if (tmp>MAX_INT) \
/test hash_hcount:=overmult(hash_hcount,8)+ascii(param)%;\
/else /test hash_hcount:=tmp%;\
/endif%;\
/let param=$[substr(param,1)]%;\
/done%;\
/if (hash_hcount<0) /let hash_hcount=$[-hash_hcount]%; /endif%;\
/result replace(".","",replace(" ","0",pad(hash_hcount,9)))%;\
/endif%;
/def overmult = \
/let number=%1%;\
/let mult=%2%;\
/let result=%number%;\
/let over=%;\
/while (--mult>0) \
/if (result+number>MAX_INT) \
/test over:=number-1-(MAX_INT-result)%;\
;/echo -- %mult over %over = %number -1 - ( %MAX_INT - %result [$[MAX_INT-result]])%;\
/test result:=-MAX_INT-1 + over %;\
;/echo -- res %result = -%MAX_INT -1 + %over%;\
/else \
/test result:=result+number%;\
/endif%;\
/done%;\
/return result
/def overflow = \
/if ({1}>MAX_INT) \
/let overflow=%;\
/test overflow:={1}-MAX_INT*trunc({1}/MAX_INT)%;\
/test overflow:=-MAX_INT-1+overflow%;\
/return overflow%;\
/endif%;\
/return {1}%;
;/if (have_ext("MD5")) \
; /def hash=/return md5({*})%;\
;/else \
; /def hash=${hash1}%;\
;/endif
/def list_idx =\
/let tmp=%1%;\
/shift%;\
/let result=0%;\
/while ({#}) \
/test ++result%;\
/if (tmp=~{1}) /result result%;/endif%;\
/shift%;\
/done%;\
/result 0%;
;;;; /qsort by Ken Keys
;;; usage: /qsort comparison-function item...
;;; Echoes the sorted items.
;;; "comparison-function" is the name of a function that compares %1 and %2,
;;; and returns <0, 0, or >0. "item..." is a series of words to be sorted.
; Using %R instead of %1 has little effect on random input, but is much
; more efficient on sorted or nearly-sorted input.
/def -i qsort = \
/if ({#} <= 2) \
/return {-1}%; \
/else \
/let compare=%{1}%;\
/shift%;\
; /let key=%{R}%;\
/let key=%{1}%;\
/let same=%;\
/let small=%;\
/let large=%;\
/let diff=%;\
/while ({#}) \
/test diff:=%compare({1}, key)%;\
/if (!diff) \
/let same=%same %1%; \
/elseif (diff < 0) \
/let small=%small %1%; \
/else \
/let large=%large %1%; \
/endif%; \
/shift%; \
/done%; \
/qsort %compare %small%;\
/let res=%? %same%;\
/qsort %compare %large%;\
/let res=%res %?%;\
; /return $(/qsort %compare %small) %same $(/qsort %compare %large)%; \
/return res%;\
/endif
;;;; /qnsort by Ken Keys
;;; usage: /qnsort F comparison-function item...
;;; Echoes the first F sorted items, instead of all N, much more efficiently
;;; than /first_n $(/qsort ...). If F < 0, it is ignored.
;;; "comparison-function" is the name of a function that compares %1 and %2,
;;; and returns <0, 0, or >0. "item..." is a series of words to be sorted.
/def -i qnsort = \
/if ({#} <= 2) \
/_echo %{-1}%; \
/else \
/let F=%{1}%; \
/let cmp=%{2}%;\
/shift 2%;\
/if (F >= {#} | F < 0) /qsort %cmp %*%; /return {?}%; /endif%; \
; /let key=%{R}%;\
/let key=%{1}%;\
/let same=%;\
/let small=%;\
/let large=%;\
/let nsame=0%;\
/let nsmall=0%;\
/let nlarge=0%;\
/let diff=%;\
/while ({#}) \
/test diff:=%cmp({1}, key)%;\
/if (!diff) \
/let same=%same %1%; \
/test ++nsame%; \
/elseif (diff < 0) \
/let small=%small %1%; \
/test ++nsmall%; \
/else \
/let large=%large %1%; \
/test ++nlarge%; \
/endif%; \
/shift%; \
/done%; \
/if (F <= nsmall) \
/_echo $(/qnsort %F %cmp %small)%; \
/elseif (F <= nsmall + nsame) \
/_echo $(/qsort %cmp %small) $(/first_n $[F-nsmall] %same)%; \
/else \
/_echo $(/qsort %cmp %small) %same \
$(/qnsort $[F - nsmall - nsame] %cmp %large)%; \
/endif%; \
/endif
;;; useful comparison functions
/def -i intcmp = /test {1} - {2}
/def -i strcasecmp = /test strcmp(tolower({1}), tolower({2}))
/addh info Evaluiert den uebergebenen String und gibt das Ergebnis zurueck, noetig, weil /eval /let a=b ist %b nicht funktioniert
/addh syn /reval String
/addh return Evaluierter String
/addh var lokal: tmp_eval
/addh reval mak
/def reval = /eval /let tmp_eval=%*\%;/return tmp_eval
/addh info Vergleicht Strings und liefert die Anzahl der Zeichen bis zu der die Strings gleich sind
/addh syn /strcmpn string1 string2
/addh return Anzahl gleicher Zeichen
/addh strcmpn mak
/def strcmpn = \
/let _maxlen=0%;\
/let _first=%;\
/let _second=%;\
/test _first:={1},_second:={2}%;\
/test _maxlen:=strlen(_first) < strlen(_second) ? strlen(_first) : strlen(_second)%;\
/let _start=0%;\
/let _len=%_maxlen%;\
; /let _count=0%;\
/while (_len > 0) \
/while (_len > 0 & strncmp(_first,_second,_start + _len)!=0) \
; /test ++_count%;\
/test _len:=_len/2%;\
/done%;\
; /echo -e %_count %_start %_len%;\
/if (_len==0 | _start + _len >= _maxlen) /result _start + _len%;/endif%;\
/test _start:=_start + _len%;\
/test _maxlen:=_start + _len%;\
/done%;\
/result _start + _len%;
/addh_fileinfo