270{
271 const uint8_t* p = static_cast<const uint8_t*>(a);
272 const uint8_t* q = static_cast<const uint8_t*>(b);
273
274 if ((size == 0) || (p == q))
275 {
276 return 0;
277 }
278
279 auto byte_cmp = [](const uint8_t* x, const uint8_t* y, size_t n) -> int
280 {
281 for (size_t i = 0; i < n; ++i)
282 {
283 int diff = static_cast<int>(x[i]) - static_cast<int>(y[i]);
284 if (diff != 0)
285 {
286 return diff;
287 }
288 }
289 return 0;
290 };
291
292 uintptr_t p_off = reinterpret_cast<uintptr_t>(p) & (LIBXR_ALIGN_SIZE - 1);
293 uintptr_t q_off = reinterpret_cast<uintptr_t>(q) & (LIBXR_ALIGN_SIZE - 1);
294
295
296 if ((p_off == q_off) && (p_off != 0))
297 {
298 size_t head = LIBXR_ALIGN_SIZE - p_off;
299 if (head > size)
300 {
301 head = size;
302 }
303
304 while (head--)
305 {
306 int diff = static_cast<int>(*p++) - static_cast<int>(*q++);
307 if (diff != 0)
308 {
309 return diff;
310 }
311 --size;
312 }
313 }
314
315#if LIBXR_ALIGN_SIZE == 8
316
317 if ((((reinterpret_cast<uintptr_t>(p) | reinterpret_cast<uintptr_t>(q)) & 7u) == 0u))
318 {
319 auto* pw = reinterpret_cast<const uint64_t*>(p);
320 auto* qw = reinterpret_cast<const uint64_t*>(q);
321
322 while (size >= 64)
323 {
324 if (pw[0] != qw[0])
325 {
326 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 0),
327 reinterpret_cast<const uint8_t*>(qw + 0), 8);
328 }
329 if (pw[1] != qw[1])
330 {
331 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 1),
332 reinterpret_cast<const uint8_t*>(qw + 1), 8);
333 }
334 if (pw[2] != qw[2])
335 {
336 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 2),
337 reinterpret_cast<const uint8_t*>(qw + 2), 8);
338 }
339 if (pw[3] != qw[3])
340 {
341 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 3),
342 reinterpret_cast<const uint8_t*>(qw + 3), 8);
343 }
344 if (pw[4] != qw[4])
345 {
346 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 4),
347 reinterpret_cast<const uint8_t*>(qw + 4), 8);
348 }
349 if (pw[5] != qw[5])
350 {
351 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 5),
352 reinterpret_cast<const uint8_t*>(qw + 5), 8);
353 }
354 if (pw[6] != qw[6])
355 {
356 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 6),
357 reinterpret_cast<const uint8_t*>(qw + 6), 8);
358 }
359 if (pw[7] != qw[7])
360 {
361 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 7),
362 reinterpret_cast<const uint8_t*>(qw + 7), 8);
363 }
364
365 pw += 8;
366 qw += 8;
367 size -= 64;
368 }
369
370 while (size >= 8)
371 {
372 if (*pw != *qw)
373 {
374 return byte_cmp(reinterpret_cast<const uint8_t*>(pw),
375 reinterpret_cast<const uint8_t*>(qw), 8);
376 }
377 ++pw;
378 ++qw;
379 size -= 8;
380 }
381
382 p = reinterpret_cast<const uint8_t*>(pw);
383 q = reinterpret_cast<const uint8_t*>(qw);
384 }
385#else
386
387 if ((((reinterpret_cast<uintptr_t>(p) | reinterpret_cast<uintptr_t>(q)) & 3u) == 0u))
388 {
389 auto* pw = reinterpret_cast<const uint32_t*>(p);
390 auto* qw = reinterpret_cast<const uint32_t*>(q);
391
392 while (size >= 32)
393 {
394 if (pw[0] != qw[0])
395 {
396 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 0),
397 reinterpret_cast<const uint8_t*>(qw + 0), 4);
398 }
399 if (pw[1] != qw[1])
400 {
401 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 1),
402 reinterpret_cast<const uint8_t*>(qw + 1), 4);
403 }
404 if (pw[2] != qw[2])
405 {
406 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 2),
407 reinterpret_cast<const uint8_t*>(qw + 2), 4);
408 }
409 if (pw[3] != qw[3])
410 {
411 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 3),
412 reinterpret_cast<const uint8_t*>(qw + 3), 4);
413 }
414 if (pw[4] != qw[4])
415 {
416 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 4),
417 reinterpret_cast<const uint8_t*>(qw + 4), 4);
418 }
419 if (pw[5] != qw[5])
420 {
421 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 5),
422 reinterpret_cast<const uint8_t*>(qw + 5), 4);
423 }
424 if (pw[6] != qw[6])
425 {
426 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 6),
427 reinterpret_cast<const uint8_t*>(qw + 6), 4);
428 }
429 if (pw[7] != qw[7])
430 {
431 return byte_cmp(reinterpret_cast<const uint8_t*>(pw + 7),
432 reinterpret_cast<const uint8_t*>(qw + 7), 4);
433 }
434
435 pw += 8;
436 qw += 8;
437 size -= 32;
438 }
439
440 while (size >= 4)
441 {
442 if (*pw != *qw)
443 {
444 return byte_cmp(reinterpret_cast<const uint8_t*>(pw),
445 reinterpret_cast<const uint8_t*>(qw), 4);
446 }
447 ++pw;
448 ++qw;
449 size -= 4;
450 }
451
452 p = reinterpret_cast<const uint8_t*>(pw);
453 q = reinterpret_cast<const uint8_t*>(qw);
454 }
455#endif
456
457
458 while (size--)
459 {
460 int diff = static_cast<int>(*p++) - static_cast<int>(*q++);
461 if (diff != 0)
462 {
463 return diff;
464 }
465 }
466
467 return 0;
468}