├── .editorconfig ├── .gitattributes ├── LICENSE.md ├── README.md ├── tdw_istring.inc ├── tdw_string.inc ├── tdw_string_test.pwn └── tdw_tstring.inc /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | 7 | [*.{inc,pwn}] 8 | indent_style = tab 9 | indent_size = 4 10 | charset = cp1251 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.inc linguist-language=PAWN -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Double V 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgement in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TDW String 2 | 3 | ### About the library 4 | The library exports several useful functions for working with strings that are not in PAWN. Almost all functions can work with packed strings. Also, it fixes some bugs in PAWN functions. 5 | 6 | ### Installation 7 | 1. Download library. 8 | 2. All files move into folder `pawno/includes`. But, you can use the flag `-i` to specify an alternative path. 9 | 3. Include it: 10 | ```PAWN 11 | #include // standart SAMP library 12 | #include 13 | ``` 14 | -------------------------------------------------------------------------------- /tdw_istring.inc: -------------------------------------------------------------------------------- 1 | /* 2 | * TDW Improved Strings 3 | * 4 | * Copyright (c) 2017 Double V 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgement in the product documentation would be 17 | * appreciated but is not required. 18 | * 2. Altered source versions must be plainly marked as such, and must not be 19 | * misrepresented as being the original software. 20 | * 3. This notice may not be removed or altered from any source distribution. 21 | */ 22 | 23 | #if defined _TDW_ISTRING_INC_ 24 | #endinput 25 | #endif 26 | #define _TDW_ISTRING_INC_ 27 | 28 | #if !defined TDW_STRING_BYTES_PER_CELL 29 | #define TDW_STRING_BYTES_PER_CELL (cellbits / charbits) 30 | #endif 31 | 32 | #define TDW_STRING_T {Str_, StrB} 33 | 34 | #define String:%0(%1) Str_:%0=Str_:istring_ref(%1) 35 | #define Str_:%0=Str_:istring_ref(%1,%2) TDWS@%0[(%2) + 1] = " " %1,\ 36 | StrB:%0=StrB:(istring_ref(((TDWS@%0[0]=(%2)),TDWS@%0)) +\ 37 | TDW_STRING_BYTES_PER_CELL) 38 | 39 | // Returns an address of a passed argument. 40 | stock istring_ref(...) 41 | { 42 | #emit load.s.pri 12 43 | #emit retn 44 | 45 | return 0; 46 | } 47 | 48 | // Returns the capacity of a string. 49 | stock istring_get_capacity(TDW_STRING_T:str, tag = tagof str) 50 | { 51 | // Different algorithms to obtain the capacity of the string. 52 | switch (tag) { 53 | case (tagof(StrB:)): { 54 | // Reads the previous cell. 55 | #emit load.s.pri str 56 | #emit add.c 0xfffffffc // -4 57 | #emit load.i 58 | #emit retn 59 | } 60 | case (tagof(Str_:)): { 61 | return istring_get_size(str); 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | // Returns the current size of a string. 69 | stock istring_get_size(TDW_STRING_T:str) 70 | { 71 | #emit push.s str 72 | #emit push.c 4 73 | 74 | #emit sysreq.c strlen 75 | 76 | #emit stack 8 77 | #emit retn 78 | 79 | return 0; 80 | } 81 | 82 | // ---------------------------------------------------------------------------- 83 | // Overloaded operators 84 | 85 | stock bool:operator==(Str_:str1, Str_:str2) 86 | { 87 | #emit push.c cellmax 88 | #emit push.c 0 89 | #emit push.s str2 90 | #emit push.s str1 91 | #emit push.c 16 92 | 93 | #emit sysreq.c strcmp 94 | 95 | #emit stack 20 96 | #emit zero.alt 97 | #emit eq 98 | #emit retn 99 | 100 | return bool:0; 101 | } 102 | stock bool:operator==(Str_:str1, StrB:str2) 103 | { 104 | #emit push.c cellmax 105 | #emit push.c 0 106 | #emit push.s str2 107 | #emit push.s str1 108 | #emit push.c 16 109 | 110 | #emit sysreq.c strcmp 111 | 112 | #emit stack 20 113 | #emit zero.alt 114 | #emit eq 115 | #emit retn 116 | 117 | return bool:0; 118 | } 119 | stock bool:operator==(StrB:str1, Str_:str2) 120 | { 121 | #emit push.c cellmax 122 | #emit push.c 0 123 | #emit push.s str2 124 | #emit push.s str1 125 | #emit push.c 16 126 | 127 | #emit sysreq.c strcmp 128 | 129 | #emit stack 20 130 | #emit zero.alt 131 | #emit eq 132 | #emit retn 133 | 134 | return bool:0; 135 | } 136 | stock bool:operator==(StrB:str1, StrB:str2) 137 | { 138 | #emit push.c cellmax 139 | #emit push.c 0 140 | #emit push.s str2 141 | #emit push.s str1 142 | #emit push.c 16 143 | 144 | #emit sysreq.c strcmp 145 | 146 | #emit stack 20 147 | #emit zero.alt 148 | #emit eq 149 | #emit retn 150 | 151 | return bool:0; 152 | } 153 | stock bool:operator!=(Str_:str1, Str_:str2) 154 | { 155 | #emit push.c cellmax 156 | #emit push.c 0 157 | #emit push.s str2 158 | #emit push.s str1 159 | #emit push.c 16 160 | 161 | #emit sysreq.c strcmp 162 | 163 | #emit stack 20 164 | #emit zero.alt 165 | #emit neq 166 | #emit retn 167 | 168 | return bool:0; 169 | } 170 | stock bool:operator!=(Str_:str1, StrB:str2) 171 | { 172 | #emit push.c cellmax 173 | #emit push.c 0 174 | #emit push.s str2 175 | #emit push.s str1 176 | #emit push.c 16 177 | 178 | #emit sysreq.c strcmp 179 | 180 | #emit stack 20 181 | #emit zero.alt 182 | #emit neq 183 | #emit retn 184 | 185 | return bool:0; 186 | } 187 | stock bool:operator!=(StrB:str1, Str_:str2) 188 | { 189 | #emit push.c cellmax 190 | #emit push.c 0 191 | #emit push.s str2 192 | #emit push.s str1 193 | #emit push.c 16 194 | 195 | #emit sysreq.c strcmp 196 | 197 | #emit stack 20 198 | #emit zero.alt 199 | #emit neq 200 | #emit retn 201 | 202 | return bool:0; 203 | } 204 | stock bool:operator!=(StrB:str1, StrB:str2) 205 | { 206 | #emit push.c cellmax 207 | #emit push.c 0 208 | #emit push.s str2 209 | #emit push.s str1 210 | #emit push.c 16 211 | 212 | #emit sysreq.c strcmp 213 | 214 | #emit stack 20 215 | #emit zero.alt 216 | #emit neq 217 | #emit retn 218 | 219 | return bool:0; 220 | } 221 | stock bool:operator>(Str_:str1, Str_:str2) 222 | { 223 | #emit push.c cellmax 224 | #emit push.c 0 225 | #emit push.s str2 226 | #emit push.s str1 227 | #emit push.c 16 228 | 229 | #emit sysreq.c strcmp 230 | 231 | #emit stack 20 232 | #emit zero.alt 233 | #emit grtr 234 | #emit retn 235 | 236 | return bool:0; 237 | } 238 | stock bool:operator>(Str_:str1, StrB:str2) 239 | { 240 | #emit push.c cellmax 241 | #emit push.c 0 242 | #emit push.s str2 243 | #emit push.s str1 244 | #emit push.c 16 245 | 246 | #emit sysreq.c strcmp 247 | 248 | #emit stack 20 249 | #emit zero.alt 250 | #emit grtr 251 | #emit retn 252 | 253 | return bool:0; 254 | } 255 | stock bool:operator>(StrB:str1, Str_:str2) 256 | { 257 | #emit push.c cellmax 258 | #emit push.c 0 259 | #emit push.s str2 260 | #emit push.s str1 261 | #emit push.c 16 262 | 263 | #emit sysreq.c strcmp 264 | 265 | #emit stack 20 266 | #emit zero.alt 267 | #emit grtr 268 | #emit retn 269 | 270 | return bool:0; 271 | } 272 | stock bool:operator>(StrB:str1, StrB:str2) 273 | { 274 | #emit push.c cellmax 275 | #emit push.c 0 276 | #emit push.s str2 277 | #emit push.s str1 278 | #emit push.c 16 279 | 280 | #emit sysreq.c strcmp 281 | 282 | #emit stack 20 283 | #emit zero.alt 284 | #emit grtr 285 | #emit retn 286 | 287 | return bool:0; 288 | } 289 | stock bool:operator<(Str_:str1, Str_:str2) 290 | { 291 | #emit push.c cellmax 292 | #emit push.c 0 293 | #emit push.s str2 294 | #emit push.s str1 295 | #emit push.c 16 296 | 297 | #emit sysreq.c strcmp 298 | 299 | #emit stack 20 300 | #emit zero.alt 301 | #emit less 302 | #emit retn 303 | 304 | return bool:0; 305 | } 306 | stock bool:operator<(Str_:str1, StrB:str2) 307 | { 308 | #emit push.c cellmax 309 | #emit push.c 0 310 | #emit push.s str2 311 | #emit push.s str1 312 | #emit push.c 16 313 | 314 | #emit sysreq.c strcmp 315 | 316 | #emit stack 20 317 | #emit zero.alt 318 | #emit less 319 | #emit retn 320 | 321 | return bool:0; 322 | } 323 | stock bool:operator<(StrB:str1, Str_:str2) 324 | { 325 | #emit push.c cellmax 326 | #emit push.c 0 327 | #emit push.s str2 328 | #emit push.s str1 329 | #emit push.c 16 330 | 331 | #emit sysreq.c strcmp 332 | 333 | #emit stack 20 334 | #emit zero.alt 335 | #emit less 336 | #emit retn 337 | 338 | return bool:0; 339 | } 340 | stock bool:operator<(StrB:str1, StrB:str2) 341 | { 342 | #emit push.c cellmax 343 | #emit push.c 0 344 | #emit push.s str2 345 | #emit push.s str1 346 | #emit push.c 16 347 | 348 | #emit sysreq.c strcmp 349 | 350 | #emit stack 20 351 | #emit zero.alt 352 | #emit less 353 | #emit retn 354 | 355 | return bool:0; 356 | } 357 | stock bool:operator>=(Str_:str1, Str_:str2) 358 | { 359 | #emit push.c cellmax 360 | #emit push.c 0 361 | #emit push.s str2 362 | #emit push.s str1 363 | #emit push.c 16 364 | 365 | #emit sysreq.c strcmp 366 | 367 | #emit stack 20 368 | #emit zero.alt 369 | #emit geq 370 | #emit retn 371 | 372 | return bool:0; 373 | } 374 | stock bool:operator>=(Str_:str1, StrB:str2) 375 | { 376 | #emit push.c cellmax 377 | #emit push.c 0 378 | #emit push.s str2 379 | #emit push.s str1 380 | #emit push.c 16 381 | 382 | #emit sysreq.c strcmp 383 | 384 | #emit stack 20 385 | #emit zero.alt 386 | #emit geq 387 | #emit retn 388 | 389 | return bool:0; 390 | } 391 | stock bool:operator>=(StrB:str1, Str_:str2) 392 | { 393 | #emit push.c cellmax 394 | #emit push.c 0 395 | #emit push.s str2 396 | #emit push.s str1 397 | #emit push.c 16 398 | 399 | #emit sysreq.c strcmp 400 | 401 | #emit stack 20 402 | #emit zero.alt 403 | #emit geq 404 | #emit retn 405 | 406 | return bool:0; 407 | } 408 | stock bool:operator>=(StrB:str1, StrB:str2) 409 | { 410 | #emit push.c cellmax 411 | #emit push.c 0 412 | #emit push.s str2 413 | #emit push.s str1 414 | #emit push.c 16 415 | 416 | #emit sysreq.c strcmp 417 | 418 | #emit stack 20 419 | #emit zero.alt 420 | #emit geq 421 | #emit retn 422 | 423 | return bool:0; 424 | } 425 | stock bool:operator<=(Str_:str1, Str_:str2) 426 | { 427 | #emit push.c cellmax 428 | #emit push.c 0 429 | #emit push.s str2 430 | #emit push.s str1 431 | #emit push.c 16 432 | 433 | #emit sysreq.c strcmp 434 | 435 | #emit stack 20 436 | #emit zero.alt 437 | #emit leq 438 | #emit retn 439 | 440 | return bool:0; 441 | } 442 | stock bool:operator<=(Str_:str1, StrB:str2) 443 | { 444 | #emit push.c cellmax 445 | #emit push.c 0 446 | #emit push.s str2 447 | #emit push.s str1 448 | #emit push.c 16 449 | 450 | #emit sysreq.c strcmp 451 | 452 | #emit stack 20 453 | #emit zero.alt 454 | #emit leq 455 | #emit retn 456 | 457 | return bool:0; 458 | } 459 | stock bool:operator<=(StrB:str1, Str_:str2) 460 | { 461 | #emit push.c cellmax 462 | #emit push.c 0 463 | #emit push.s str2 464 | #emit push.s str1 465 | #emit push.c 16 466 | 467 | #emit sysreq.c strcmp 468 | 469 | #emit stack 20 470 | #emit zero.alt 471 | #emit leq 472 | #emit retn 473 | 474 | return bool:0; 475 | } 476 | stock bool:operator<=(StrB:str1, StrB:str2) 477 | { 478 | #emit push.c cellmax 479 | #emit push.c 0 480 | #emit push.s str2 481 | #emit push.s str1 482 | #emit push.c 16 483 | 484 | #emit sysreq.c strcmp 485 | 486 | #emit stack 20 487 | #emit zero.alt 488 | #emit leq 489 | #emit retn 490 | 491 | return bool:0; 492 | } 493 | -------------------------------------------------------------------------------- /tdw_string.inc: -------------------------------------------------------------------------------- 1 | /* 2 | * TDW String 3 | * 4 | * Copyright (c) 2017 Double V 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgement in the product documentation would be 17 | * appreciated but is not required. 18 | * 2. Altered source versions must be plainly marked as such, and must not be 19 | * misrepresented as being the original software. 20 | * 3. This notice may not be removed or altered from any source distribution. 21 | */ 22 | 23 | #if defined _TDW_STRING_INC_ 24 | #endinput 25 | #endif 26 | #define _TDW_STRING_INC_ 27 | 28 | #if !defined TDW_STRING_IS_PACKED 29 | #define TDW_STRING_IS_PACKED(%0) ((%0){0} != 0) 30 | #endif 31 | 32 | #if !defined TDW_STRING_BYTES_PER_CELL 33 | #define TDW_STRING_BYTES_PER_CELL (cellbits / charbits) 34 | #endif 35 | 36 | enum e_TDW_FILL_TYPE (<<= 1) 37 | { 38 | ei_TDW_FILL_TYPE_LEFT = 1, 39 | ei_TDW_FILL_TYPE_RIGHT, 40 | ei_TDW_FILL_TYPE_BOTH = ei_TDW_FILL_TYPE_LEFT | ei_TDW_FILL_TYPE_RIGHT 41 | }; 42 | 43 | // Returns true if a passed string is empty, otherwise returns false. 44 | stock isempty(const str[]) 45 | { 46 | return str[0] == EOS; 47 | } 48 | 49 | // Returns true if a passed string contains only a number, otherwise return 50 | // false. 51 | stock isnum(const str[]) 52 | { 53 | new 54 | i, 55 | temp; 56 | 57 | while ((temp = str[i++]) != EOS) { 58 | switch (temp) { 59 | case '0'..'9': 60 | continue; 61 | case '+', '-', '.': 62 | continue; 63 | default: 64 | return 0; 65 | } 66 | } 67 | return 1; 68 | } 69 | 70 | // Moves the indicator string end to the beginning. 71 | stock strclr(str[]) 72 | { 73 | return str[0] = EOS; 74 | } 75 | 76 | // Copies a source string to a destination string. Returns the number of 77 | // copied characters. 78 | stock strcpy(dest[], const src[], maxlength=sizeof dest) 79 | { 80 | strclr(dest); 81 | return strcat(dest, src, maxlength); 82 | } 83 | 84 | // Reverses a string. Returns the number of replaced characters. 85 | stock strrev(str[]) 86 | { 87 | new 88 | length = strlen(str), 89 | i, 90 | j = length - 1, 91 | temp; 92 | 93 | if (TDW_STRING_IS_PACKED(str)) { 94 | length *= TDW_STRING_BYTES_PER_CELL; 95 | 96 | do { 97 | temp = str{i}; 98 | str{i++} = str{j}; 99 | str{j--} = temp; 100 | } while (i < j); 101 | } else { 102 | do { 103 | temp = str[i]; 104 | str[i++] = str[j]; 105 | str[j--] = temp; 106 | } while (i < j); 107 | } 108 | return i; 109 | } 110 | 111 | // Counts the number of matches. Returns the number of matches. 112 | stock strcnt(const src[], const sub[], bool:ignorecase=false) 113 | { 114 | new 115 | last_pos, 116 | cnt, 117 | sub_length = strlen(sub); 118 | 119 | if (TDW_STRING_IS_PACKED(sub)) 120 | sub_length *= TDW_STRING_BYTES_PER_CELL; 121 | 122 | while ((last_pos = strfind(src, sub, ignorecase, last_pos)) >= 0) 123 | { 124 | last_pos += sub_length; 125 | cnt++; 126 | } 127 | 128 | return cnt; 129 | } 130 | 131 | // Returns an index of the first occurrence of character in the str. 132 | stock strchr(const str[], chr) 133 | { 134 | new 135 | cur_chr, 136 | pos; 137 | 138 | if (TDW_STRING_IS_PACKED(str)) { 139 | while ((cur_chr = str{pos}) && cur_chr != chr) 140 | pos++; 141 | } else { 142 | while ((cur_chr = str[pos]) && cur_chr != chr) 143 | pos++; 144 | } 145 | 146 | return pos; 147 | } 148 | 149 | stock strspn(const str1[], const str2[]) 150 | { 151 | new 152 | str1_chr, 153 | str1_pos, 154 | str2_chr, 155 | str2_pos; 156 | 157 | if (TDW_STRING_IS_PACKED(str1)) { 158 | if (TDW_STRING_IS_PACKED(str2)) { 159 | while ((str1_chr = str1{str1_pos})) { 160 | while ((str2_chr = str2{str2_pos}) && str1_chr != str2_chr) 161 | str2_pos++; 162 | 163 | if (str2_chr != EOS) 164 | break; 165 | 166 | str2_pos = 0; 167 | str1_pos++; 168 | } 169 | } else { 170 | while ((str1_chr = str1{str1_pos})) { 171 | while ((str2_chr = str2[str2_pos]) && str1_chr != str2_chr) 172 | str2_pos++; 173 | 174 | if (str2_chr != EOS) 175 | break; 176 | 177 | str2_pos = 0; 178 | str1_pos++; 179 | } 180 | } 181 | } else { 182 | if (TDW_STRING_IS_PACKED(str2)) { 183 | while ((str1_chr = str1[str1_pos])) { 184 | while ((str2_chr = str2{str2_pos}) && str1_chr != str2_chr) 185 | str2_pos++; 186 | 187 | if (str2_chr != EOS) 188 | break; 189 | 190 | str2_pos = 0; 191 | str1_pos++; 192 | } 193 | } else { 194 | while ((str1_chr = str1[str1_pos])) { 195 | while ((str2_chr = str2[str2_pos]) && str1_chr != str2_chr) 196 | str2_pos++; 197 | 198 | if (str2_chr != EOS) 199 | break; 200 | 201 | str2_pos = 0; 202 | str1_pos++; 203 | } 204 | } 205 | } 206 | 207 | return str1_pos; 208 | } 209 | -------------------------------------------------------------------------------- /tdw_string_test.pwn: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | public OnFilterScriptInit() 8 | { 9 | new buffer[10]; 10 | 11 | print(!"\n=============== [ IS* FUNCTIONS ] ==============="); 12 | printf("isempty(buffer) %d" , isempty(buffer)); 13 | printf("isnum(\"123456\") %d", isnum("123456")); 14 | 15 | print(!"\n=============== [ STR* FUNCTIONS ] ==============="); 16 | strcpy(buffer, "Local"); 17 | printf("strcpy(buffer, \"Local\") now buffer stores `%s`;", buffer); 18 | strrev(buffer); 19 | printf("strrev(buffer) now buffer stores `%s`;", buffer); 20 | printf("strcnt(buffer, \"l\", .ignorecase=true) returns %d;", strcnt(buffer, "l", .ignorecase = true)); 21 | printf("strchr(buffer, 'a') returns %d;", strchr(buffer, 'a')); 22 | printf("strspn(buffer, \"abc\") returns %d", strspn(buffer, "abc")); 23 | strclr(buffer); 24 | printf("strclr(buffer) now buffer stores `%s` - nothing;", buffer); 25 | 26 | new String:abc1("This thing is important"); 27 | new String:abc2("This thing is important"); 28 | printf("istring_get_capacity(abc1) returns %d", istring_get_capacity(abc1)); 29 | printf("istring_get_size(abc1) returns %d", istring_get_size(abc1)); 30 | 31 | if (abc1 == abc2) 32 | printf("abc1 == abc2"); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tdw_tstring.inc: -------------------------------------------------------------------------------- 1 | /* 2 | * TDW Type 3 | * 4 | * Copyright (c) 2017 Double V 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgement in the product documentation would be 17 | * appreciated but is not required. 18 | * 2. Altered source versions must be plainly marked as such, and must not be 19 | * misrepresented as being the original software. 20 | * 3. This notice may not be removed or altered from any source distribution. 21 | */ 22 | 23 | #if defined _TDW_TSTRING_INC_ 24 | #endinput 25 | #endif 26 | #define _TDW_TSTRING_INC_ 27 | 28 | #define iscntrl(%0) ((0x00 <= (%0) < 0x20) || ((%0) == 0x7f)) 29 | #define isblank(%0) (((%0) == 0x09) || ((%0) == 0x20)) 30 | #define isspace(%0) (0x09 <= (%0) <= 0x20) 31 | #define isupper(%0) (0x41 <= (%0) <= 0x5a) 32 | #define islower(%0) (0x61 <= (%0) <= 0x7a) 33 | #define isalpha(%0) (isupper(%0) || islower(%0)) 34 | #define isdigit(%0) (0x30 <= (%0) <= 0x39) 35 | #define isxdigit(%0) (isdigit(%0) || (0x41 <= (%0) <= 0x46) || (0x61 <= (%0) <= 0x66)) 36 | #define isalnum(%0) (isdigit(%0) || isalpha(%0)) 37 | #define ispunct(%0) ((0x21 <= (%0) <= 0x2f) || (0x3a <= (%0) <= 0x40) || (0x5b <= (%0) <= 0x60) || (0x7b <= (%0) <= 0x7e)) 38 | #define isgraph(%0) (0x21 <= (%0) <= 0x7e) 39 | #define isprint(%0) (0x20 <= (%0) <= 0x7e) 40 | --------------------------------------------------------------------------------