1 /* 2 ********************************************************************** 3 * Copyright (c) 2002-2014, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 ********************************************************************** 7 */ 8 /** 9 * This Program tests the performance of ICU's Normalization engine against Windows 10 * to run it use the command like 11 * 12 * c:\normperf.exe -s C:\work\ICUCupertinoRep\icu4c\collation-perf-data -i 10 -p 15 -f TestNames_Asian.txt -u -e UTF-8 -l 13 */ 14 #include "normperf.h" 15 #include "uoptions.h" 16 #include "cmemory.h" // for UPRV_LENGTHOF 17 #include <stdio.h> 18 19 UPerfFunction* NormalizerPerformanceTest::runIndexedTest(int32_t index, UBool exec,const char* &name, char* par) { 20 switch (index) { 21 TESTCASE(0,TestICU_NFC_NFD_Text); 22 TESTCASE(1,TestICU_NFC_NFC_Text); 23 TESTCASE(2,TestICU_NFC_Orig_Text); 24 25 TESTCASE(3,TestICU_NFD_NFD_Text); 26 TESTCASE(4,TestICU_NFD_NFC_Text); 27 TESTCASE(5,TestICU_NFD_Orig_Text); 28 29 TESTCASE(6,TestICU_FCD_NFD_Text); 30 TESTCASE(7,TestICU_FCD_NFC_Text); 31 TESTCASE(8,TestICU_FCD_Orig_Text); 32 33 TESTCASE(9,TestWin_NFC_NFD_Text); 34 TESTCASE(10,TestWin_NFC_NFC_Text); 35 TESTCASE(11,TestWin_NFC_Orig_Text); 36 37 TESTCASE(12,TestWin_NFD_NFD_Text); 38 TESTCASE(13,TestWin_NFD_NFC_Text); 39 TESTCASE(14,TestWin_NFD_Orig_Text); 40 41 TESTCASE(15,TestQC_NFC_NFD_Text); 42 TESTCASE(16,TestQC_NFC_NFC_Text); 43 TESTCASE(17,TestQC_NFC_Orig_Text); 44 45 TESTCASE(18,TestQC_NFD_NFD_Text); 46 TESTCASE(19,TestQC_NFD_NFC_Text); 47 TESTCASE(20,TestQC_NFD_Orig_Text); 48 49 TESTCASE(21,TestQC_FCD_NFD_Text); 50 TESTCASE(22,TestQC_FCD_NFC_Text); 51 TESTCASE(23,TestQC_FCD_Orig_Text); 52 53 TESTCASE(24,TestIsNormalized_NFC_NFD_Text); 54 TESTCASE(25,TestIsNormalized_NFC_NFC_Text); 55 TESTCASE(26,TestIsNormalized_NFC_Orig_Text); 56 57 TESTCASE(27,TestIsNormalized_NFD_NFD_Text); 58 TESTCASE(28,TestIsNormalized_NFD_NFC_Text); 59 TESTCASE(29,TestIsNormalized_NFD_Orig_Text); 60 61 TESTCASE(30,TestIsNormalized_FCD_NFD_Text); 62 TESTCASE(31,TestIsNormalized_FCD_NFC_Text); 63 TESTCASE(32,TestIsNormalized_FCD_Orig_Text); 64 65 default: 66 name = ""; 67 return NULL; 68 } 69 return NULL; 70 71 } 72 73 void NormalizerPerformanceTest::normalizeInput(ULine* dest,const UChar* src ,int32_t srcLen,UNormalizationMode mode, int32_t options){ 74 int32_t reqLen = 0; 75 UErrorCode status = U_ZERO_ERROR; 76 for(;;){ 77 /* pure pre-flight */ 78 reqLen=unorm_normalize(src,srcLen,mode, options,NULL,0,&status); 79 if(status==U_BUFFER_OVERFLOW_ERROR){ 80 status=U_ZERO_ERROR; 81 dest->name = new UChar[reqLen+1]; 82 reqLen= unorm_normalize(src,srcLen,mode, options,dest->name,reqLen+1,&status); 83 dest->len=reqLen; 84 break; 85 }else if(U_FAILURE(status)){ 86 printf("Could not normalize input. Error: %s", u_errorName(status)); 87 } 88 } 89 } 90 UChar* NormalizerPerformanceTest::normalizeInput(int32_t& len, const UChar* src ,int32_t srcLen,UNormalizationMode mode, int32_t options){ 91 int32_t reqLen = 0; 92 UErrorCode status = U_ZERO_ERROR; 93 UChar* dest = NULL; 94 for(;;){ 95 /* pure pre-flight */ 96 reqLen=unorm_normalize(src,srcLen,mode, options,NULL,0,&status); 97 if(status==U_BUFFER_OVERFLOW_ERROR){ 98 status=U_ZERO_ERROR; 99 dest = new UChar[reqLen+1]; 100 reqLen= unorm_normalize(src,srcLen,mode, options,dest,reqLen+1,&status); 101 len=reqLen; 102 break; 103 }else if(U_FAILURE(status)){ 104 printf("Could not normalize input. Error: %s", u_errorName(status)); 105 return NULL; 106 } 107 } 108 return dest; 109 } 110 111 static UOption cmdLineOptions[]={ 112 UOPTION_DEF("options", 'o', UOPT_OPTIONAL_ARG) 113 }; 114 115 NormalizerPerformanceTest::NormalizerPerformanceTest(int32_t argc, const char* argv[], UErrorCode& status) 116 : UPerfTest(argc,argv,status), options(0) { 117 NFDBuffer = NULL; 118 NFCBuffer = NULL; 119 NFDBufferLen = 0; 120 NFCBufferLen = 0; 121 NFDFileLines = NULL; 122 NFCFileLines = NULL; 123 124 if(status== U_ILLEGAL_ARGUMENT_ERROR){ 125 fprintf(stderr,gUsageString, "normperf"); 126 return; 127 } 128 129 if(U_FAILURE(status)){ 130 fprintf(stderr, "FAILED to create UPerfTest object. Error: %s\n", u_errorName(status)); 131 return; 132 } 133 134 _remainingArgc = u_parseArgs(_remainingArgc, (char **)argv, (int32_t)(UPRV_LENGTHOF(cmdLineOptions)), cmdLineOptions); 135 if(cmdLineOptions[0].doesOccur && cmdLineOptions[0].value!=NULL) { 136 options=(int32_t)strtol(cmdLineOptions[0].value, NULL, 16); 137 } 138 139 if(line_mode){ 140 ULine* filelines = getLines(status); 141 if(U_FAILURE(status)){ 142 fprintf(stderr, "FAILED to read lines from file and create UPerfTest object. Error: %s\n", u_errorName(status)); 143 return; 144 } 145 NFDFileLines = new ULine[numLines]; 146 NFCFileLines = new ULine[numLines]; 147 148 for(int32_t i=0;i<numLines;i++){ 149 normalizeInput(&NFDFileLines[i],filelines[i].name,filelines[i].len,UNORM_NFD, options); 150 normalizeInput(&NFCFileLines[i],filelines[i].name,filelines[i].len,UNORM_NFC, options); 151 152 } 153 }else if(bulk_mode){ 154 int32_t srcLen = 0; 155 const UChar* src = getBuffer(srcLen,status); 156 NFDBufferLen = 0; 157 NFCBufferLen = 0; 158 159 if(U_FAILURE(status)){ 160 fprintf(stderr, "FAILED to read buffer from file and create UPerfTest object. Error: %s\n", u_errorName(status)); 161 return; 162 } 163 164 NFDBuffer = normalizeInput(NFDBufferLen,src,srcLen,UNORM_NFD, options); 165 NFCBuffer = normalizeInput(NFCBufferLen,src,srcLen,UNORM_NFC, options); 166 } 167 168 } 169 170 NormalizerPerformanceTest::~NormalizerPerformanceTest(){ 171 delete[] NFDFileLines; 172 delete[] NFCFileLines; 173 delete[] NFDBuffer; 174 delete[] NFCBuffer; 175 } 176 177 // Test NFC Performance 178 UPerfFunction* NormalizerPerformanceTest::TestICU_NFC_NFD_Text(){ 179 if(line_mode){ 180 NormPerfFunction* func= new NormPerfFunction(ICUNormNFC, options,NFDFileLines,numLines, uselen); 181 return func; 182 }else{ 183 NormPerfFunction* func= new NormPerfFunction(ICUNormNFC, options,NFDBuffer, NFDBufferLen, uselen); 184 return func; 185 } 186 } 187 UPerfFunction* NormalizerPerformanceTest::TestICU_NFC_NFC_Text(){ 188 if(line_mode){ 189 NormPerfFunction* func = new NormPerfFunction(ICUNormNFC, options,NFCFileLines,numLines, uselen); 190 return func; 191 }else{ 192 NormPerfFunction* func= new NormPerfFunction(ICUNormNFC, options,NFCBuffer, NFCBufferLen, uselen); 193 return func; 194 } 195 } 196 UPerfFunction* NormalizerPerformanceTest::TestICU_NFC_Orig_Text(){ 197 if(line_mode){ 198 NormPerfFunction* func = new NormPerfFunction(ICUNormNFC, options,lines,numLines, uselen); 199 return func; 200 }else{ 201 NormPerfFunction* func = new NormPerfFunction(ICUNormNFC, options,buffer, bufferLen, uselen); 202 return func; 203 } 204 } 205 206 // Test NFD Performance 207 UPerfFunction* NormalizerPerformanceTest::TestICU_NFD_NFD_Text(){ 208 if(line_mode){ 209 NormPerfFunction* func = new NormPerfFunction(ICUNormNFD, options,NFDFileLines,numLines, uselen); 210 return func; 211 }else{ 212 NormPerfFunction* func = new NormPerfFunction(ICUNormNFD, options,NFDBuffer,NFDBufferLen, uselen); 213 return func; 214 } 215 } 216 UPerfFunction* NormalizerPerformanceTest::TestICU_NFD_NFC_Text(){ 217 if(line_mode){ 218 NormPerfFunction* func = new NormPerfFunction(ICUNormNFD, options,NFCFileLines,numLines, uselen); 219 return func; 220 }else{ 221 NormPerfFunction* func = new NormPerfFunction(ICUNormNFD, options,NFCBuffer,NFCBufferLen, uselen); 222 return func; 223 } 224 } 225 UPerfFunction* NormalizerPerformanceTest::TestICU_NFD_Orig_Text(){ 226 if(line_mode){ 227 NormPerfFunction* func = new NormPerfFunction(ICUNormNFD, options,lines,numLines, uselen); 228 return func; 229 }else{ 230 NormPerfFunction* func = new NormPerfFunction(ICUNormNFD, options,buffer,bufferLen, uselen); 231 return func; 232 } 233 } 234 235 // Test FCD Performance 236 UPerfFunction* NormalizerPerformanceTest::TestICU_FCD_NFD_Text(){ 237 if(line_mode){ 238 NormPerfFunction* func = new NormPerfFunction(ICUNormFCD, options,NFDFileLines,numLines, uselen); 239 return func; 240 }else{ 241 NormPerfFunction* func = new NormPerfFunction(ICUNormFCD, options,NFDBuffer,NFDBufferLen, uselen); 242 return func; 243 } 244 245 } 246 UPerfFunction* NormalizerPerformanceTest::TestICU_FCD_NFC_Text(){ 247 if(line_mode){ 248 NormPerfFunction* func = new NormPerfFunction(ICUNormFCD, options,NFCFileLines,numLines, uselen); 249 return func; 250 }else{ 251 NormPerfFunction* func = new NormPerfFunction(ICUNormFCD, options,NFCBuffer,NFCBufferLen, uselen); 252 return func; 253 } 254 } 255 UPerfFunction* NormalizerPerformanceTest::TestICU_FCD_Orig_Text(){ 256 if(line_mode){ 257 NormPerfFunction* func = new NormPerfFunction(ICUNormFCD, options,lines,numLines, uselen); 258 return func; 259 }else{ 260 NormPerfFunction* func = new NormPerfFunction(ICUNormFCD, options,buffer,bufferLen, uselen); 261 return func; 262 } 263 } 264 265 // Test Win NFC Performance 266 UPerfFunction* NormalizerPerformanceTest::TestWin_NFC_NFD_Text(){ 267 if(line_mode){ 268 NormPerfFunction* func = new NormPerfFunction(WinNormNFC, options,NFDFileLines,numLines, uselen); 269 return func; 270 }else{ 271 NormPerfFunction* func = new NormPerfFunction(WinNormNFC, options,NFDBuffer,NFDBufferLen, uselen); 272 return func; 273 } 274 } 275 UPerfFunction* NormalizerPerformanceTest::TestWin_NFC_NFC_Text(){ 276 if(line_mode){ 277 NormPerfFunction* func = new NormPerfFunction(WinNormNFC, options,NFCFileLines,numLines, uselen); 278 return func; 279 }else{ 280 NormPerfFunction* func = new NormPerfFunction(WinNormNFC, options,NFCBuffer,NFCBufferLen, uselen); 281 return func; 282 } 283 } 284 UPerfFunction* NormalizerPerformanceTest::TestWin_NFC_Orig_Text(){ 285 if(line_mode){ 286 NormPerfFunction* func = new NormPerfFunction(WinNormNFC, options,lines,numLines, uselen); 287 return func; 288 }else{ 289 NormPerfFunction* func = new NormPerfFunction(WinNormNFC, options,buffer,bufferLen, uselen); 290 return func; 291 } 292 } 293 294 // Test Win NFD Performance 295 UPerfFunction* NormalizerPerformanceTest::TestWin_NFD_NFD_Text(){ 296 if(line_mode){ 297 NormPerfFunction* func = new NormPerfFunction(WinNormNFD, options,NFDFileLines,numLines, uselen); 298 return func; 299 }else{ 300 NormPerfFunction* func = new NormPerfFunction(WinNormNFD, options,NFDBuffer,NFDBufferLen, uselen); 301 return func; 302 } 303 } 304 UPerfFunction* NormalizerPerformanceTest::TestWin_NFD_NFC_Text(){ 305 if(line_mode){ 306 NormPerfFunction* func = new NormPerfFunction(WinNormNFD, options,NFCFileLines,numLines, uselen); 307 return func; 308 }else{ 309 NormPerfFunction* func = new NormPerfFunction(WinNormNFD, options,NFCBuffer,NFCBufferLen, uselen); 310 return func; 311 } 312 } 313 UPerfFunction* NormalizerPerformanceTest::TestWin_NFD_Orig_Text(){ 314 if(line_mode){ 315 NormPerfFunction* func = new NormPerfFunction(WinNormNFD, options,lines,numLines, uselen); 316 return func; 317 }else{ 318 NormPerfFunction* func = new NormPerfFunction(WinNormNFD, options,buffer,bufferLen, uselen); 319 return func; 320 } 321 } 322 323 // Test Quick Check Performance 324 UPerfFunction* NormalizerPerformanceTest::TestQC_NFC_NFD_Text(){ 325 if(line_mode){ 326 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFDFileLines, numLines, UNORM_NFC, options,uselen); 327 return func; 328 }else{ 329 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFDBuffer, NFDBufferLen, UNORM_NFC, options,uselen); 330 return func; 331 } 332 } 333 UPerfFunction* NormalizerPerformanceTest::TestQC_NFC_NFC_Text(){ 334 if(line_mode){ 335 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFCFileLines, numLines, UNORM_NFC, options,uselen); 336 return func; 337 }else{ 338 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFCBuffer, NFCBufferLen, UNORM_NFC, options,uselen); 339 return func; 340 } 341 } 342 UPerfFunction* NormalizerPerformanceTest::TestQC_NFC_Orig_Text(){ 343 if(line_mode){ 344 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,lines, numLines, UNORM_NFC, options,uselen); 345 return func; 346 }else{ 347 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,buffer, bufferLen, UNORM_NFC, options,uselen); 348 return func; 349 } 350 } 351 352 UPerfFunction* NormalizerPerformanceTest::TestQC_NFD_NFD_Text(){ 353 if(line_mode){ 354 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFDFileLines, numLines, UNORM_NFD, options,uselen); 355 return func; 356 }else{ 357 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFDBuffer, NFDBufferLen, UNORM_NFD, options,uselen); 358 return func; 359 } 360 } 361 UPerfFunction* NormalizerPerformanceTest::TestQC_NFD_NFC_Text(){ 362 if(line_mode){ 363 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFCFileLines, numLines, UNORM_NFD, options,uselen); 364 return func; 365 }else{ 366 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFCBuffer, NFCBufferLen, UNORM_NFD, options,uselen); 367 return func; 368 } 369 } 370 UPerfFunction* NormalizerPerformanceTest::TestQC_NFD_Orig_Text(){ 371 if(line_mode){ 372 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,lines, numLines, UNORM_NFD, options,uselen); 373 return func; 374 }else{ 375 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,buffer, bufferLen, UNORM_NFD, options,uselen); 376 return func; 377 } 378 } 379 380 UPerfFunction* NormalizerPerformanceTest::TestQC_FCD_NFD_Text(){ 381 if(line_mode){ 382 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFDFileLines, numLines, UNORM_FCD, options,uselen); 383 return func; 384 }else{ 385 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFDBuffer, NFDBufferLen, UNORM_FCD, options,uselen); 386 return func; 387 } 388 } 389 UPerfFunction* NormalizerPerformanceTest::TestQC_FCD_NFC_Text(){ 390 if(line_mode){ 391 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFCFileLines, numLines, UNORM_FCD, options,uselen); 392 return func; 393 }else{ 394 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,NFCBuffer, NFCBufferLen, UNORM_FCD, options,uselen); 395 return func; 396 } 397 } 398 UPerfFunction* NormalizerPerformanceTest::TestQC_FCD_Orig_Text(){ 399 if(line_mode){ 400 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,lines, numLines, UNORM_FCD, options,uselen); 401 return func; 402 }else{ 403 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUQuickCheck,buffer, bufferLen, UNORM_FCD, options,uselen); 404 return func; 405 } 406 } 407 408 // Test isNormalized Performance 409 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_NFC_NFD_Text(){ 410 if(line_mode){ 411 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFDFileLines, numLines, UNORM_NFC, options,uselen); 412 return func; 413 }else{ 414 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFDBuffer, NFDBufferLen, UNORM_NFC, options,uselen); 415 return func; 416 } 417 } 418 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_NFC_NFC_Text(){ 419 if(line_mode){ 420 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFCFileLines, numLines, UNORM_NFC, options,uselen); 421 return func; 422 }else{ 423 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFCBuffer, NFCBufferLen, UNORM_NFC, options,uselen); 424 return func; 425 } 426 } 427 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_NFC_Orig_Text(){ 428 if(line_mode){ 429 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,lines, numLines, UNORM_NFC, options,uselen); 430 return func; 431 }else{ 432 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,buffer, bufferLen, UNORM_NFC, options,uselen); 433 return func; 434 } 435 } 436 437 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_NFD_NFD_Text(){ 438 if(line_mode){ 439 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFDFileLines, numLines, UNORM_NFD, options,uselen); 440 return func; 441 }else{ 442 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFDBuffer, NFDBufferLen, UNORM_NFD, options,uselen); 443 return func; 444 } 445 } 446 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_NFD_NFC_Text(){ 447 if(line_mode){ 448 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFCFileLines, numLines, UNORM_NFD, options,uselen); 449 return func; 450 }else{ 451 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFCBuffer, NFCBufferLen, UNORM_NFD, options,uselen); 452 return func; 453 } 454 } 455 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_NFD_Orig_Text(){ 456 if(line_mode){ 457 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,lines, numLines, UNORM_NFD, options,uselen); 458 return func; 459 }else{ 460 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,buffer, bufferLen, UNORM_NFD, options,uselen); 461 return func; 462 } 463 } 464 465 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_FCD_NFD_Text(){ 466 if(line_mode){ 467 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFDFileLines, numLines, UNORM_FCD, options,uselen); 468 return func; 469 }else{ 470 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFDBuffer, NFDBufferLen, UNORM_FCD, options,uselen); 471 return func; 472 } 473 } 474 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_FCD_NFC_Text(){ 475 if(line_mode){ 476 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFCFileLines, numLines, UNORM_FCD, options,uselen); 477 return func; 478 }else{ 479 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,NFCBuffer, NFCBufferLen, UNORM_FCD, options,uselen); 480 return func; 481 } 482 } 483 UPerfFunction* NormalizerPerformanceTest::TestIsNormalized_FCD_Orig_Text(){ 484 if(line_mode){ 485 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,lines, numLines, UNORM_FCD, options,uselen); 486 return func; 487 }else{ 488 QuickCheckPerfFunction* func = new QuickCheckPerfFunction(ICUIsNormalized,buffer, bufferLen, UNORM_FCD, options,uselen); 489 return func; 490 } 491 } 492 493 int main(int argc, const char* argv[]){ 494 UErrorCode status = U_ZERO_ERROR; 495 NormalizerPerformanceTest test(argc, argv, status); 496 if(U_FAILURE(status)){ 497 return status; 498 } 499 if(test.run()==FALSE){ 500 fprintf(stderr,"FAILED: Tests could not be run please check the arguments.\n"); 501 return -1; 502 } 503 return 0; 504 } 505