source: trunk/kLdr/kLdrHlp.c@ 2881

Last change on this file since 2881 was 2881, checked in by bird, 19 years ago

kLdrHlpMemMove (not optimial).

  • Property svn:keywords set to Id
File size: 21.2 KB
Line 
1/* $Id: kLdrHlp.c 2881 2006-11-13 20:37:23Z bird $ */
2/** @file
3 *
4 * kLdr - The Dynamic Loader, Helper Functions.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#ifdef __OS2__
32# define INCL_BASE
33# define INCL_ERRORS
34# include <os2.h>
35#elif defined(__WIN__)
36# include <Windows.h>
37#else
38# error "port me"
39#endif
40
41#include <kLdr.h>
42#include "kLdrHlp.h"
43
44
45/*******************************************************************************
46* Global Variables *
47*******************************************************************************/
48#ifdef __OS2__
49/** The loader sempahore. */
50static HMTX g_hmtx;
51/** The base of the stub object.
52 * The OS/2 exe stub consists of a single data object. When allocating memory
53 * for an executable, we'll have to reuse this. */
54static void *g_pvStub = NULL;
55/** The size of the stub object - 0 if no stub. */
56static size_t g_cbStub = 0;
57
58#elif defined(__WIN__)
59/** The loader sempahore. */
60static CRITICAL_SECTION g_CritSect;
61/** The system info. */
62static SYSTEM_INFO g_SystemInfo;
63#else
64# error "port me"
65#endif
66
67
68/**
69 * Initializes the loader semaphore.
70 *
71 * @returns 0 on success, non-zero OS status code on failure.
72 */
73int kldrHlpSemInit(void)
74{
75#ifdef __OS2__
76 APIRET rc;
77 g_hmtx = NULLHANDLE;
78 rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE);
79 if (rc)
80 return rc;
81
82#elif defined(__WIN__)
83 InitializeCriticalSection(&g_CritSect);
84
85#else
86# error "port me"
87#endif
88 return 0;
89}
90
91
92/**
93 * Terminates the loader semaphore.
94 */
95void kldrHlpSemTerm(void)
96{
97#ifdef __OS2__
98 APIRET rc;
99 HMTX hmtx = g_hmtx;
100 g_hmtx = NULLHANDLE;
101 rc = DosCloseMutexSem(hmtx);
102 if (rc)
103 return rc;
104
105#elif defined(__WIN__)
106 DeleteCriticalSection(&g_CritSect);
107
108#else
109# error "port me"
110#endif
111}
112
113
114/**
115 * Requests the loader sempahore ownership.
116 * This can be done recursivly.
117 *
118 * @returns 0 on success, non-zero OS status code on failure.
119 */
120int kldrHlpSemRequest(void)
121{
122#ifdef __OS2__
123 APIRET rc = DosRequestMutexSem(g_hmtx, 5000);
124 if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT)
125 {
126 unsigned i = 0;
127 do
128 {
129 /** @todo check for deadlocks etc. */
130 rc = DosRequestMutexSem(g_hmtx, 1000);
131 } while ( ( rc == ERROR_TIMEOUT
132 || rc == ERROR_SEM_TIMEOUT
133 || rc == ERROR_INTERRUPT)
134 && i++ < 120);
135 }
136 return rc;
137
138#elif defined(__WIN__)
139 EnterCriticalSection(&g_CritSect);
140 return 0;
141
142#else
143# error "port me"
144#endif
145}
146
147
148/**
149 * Releases the loader semaphore ownership.
150 * The caller is responsible for making sure it's the semaphore owner!
151 */
152void kldrHlpSemRelease(void)
153{
154#ifdef __OS2__
155 APIRET rc = DosReleaseMutexSem(g_hmtx);
156 kldrHlpAssert(!rc); (void)rc;
157
158#elif defined(__WIN__)
159 LeaveCriticalSection(&g_CritSect);
160
161#else
162# error "port me"
163#endif
164
165}
166
167#ifdef __OS2__
168static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt)
169{
170 switch (enmProt)
171 {
172 case KLDRPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE;
173 case KLDRPROT_READONLY: return PAG_COMMIT | PAG_READ;
174 case KLDRPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE;
175 case KLDRPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE;
176 case KLDRPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
177 case KLDRPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
178 default:
179 kldrHlpAssert(0);
180 return ~0U;
181 }
182}
183#elif defined(__WIN__)
184static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt)
185{
186 switch (enmProt)
187 {
188 case KLDRPROT_NOACCESS: return PAGE_NOACCESS;
189 case KLDRPROT_READONLY: return PAGE_READONLY;
190 case KLDRPROT_READWRITE: return PAGE_READWRITE;
191 case KLDRPROT_EXECUTE: return PAGE_EXECUTE;
192 case KLDRPROT_EXECUTE_READ: return PAGE_EXECUTE_READ;
193 case KLDRPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE;
194 default:
195 kldrHlpAssert(0);
196 return ~0U;
197 }
198}
199#endif
200
201
202/**
203 * Allocate a chunk of memory with page granularity.
204 *
205 * @returns 0 on success, non-zero OS status code on failure.
206 * @param ppv Where to store the address of the allocated memory.
207 * If fFixed is set, *ppv will on entry contain the desired address (page aligned).
208 * @param cb Number of bytes. Page aligned.
209 * @param enmProt The new protection. Copy-on-write is invalid.
210 */
211int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed)
212{
213#ifdef __OS2__
214 APIRET rc;
215 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
216
217 if (!fFixed)
218 {
219 /* simple */
220 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
221 if (rc == ERROR_INVALID_PARAMETER)
222 rc = DosAllocMem(ppv, cb, fFlags);
223 }
224 else
225 {
226 /* not so simple. */
227 /** @todo I've got code for this in libc somewhere. */
228 }
229 if (!rc)
230 return 0;
231 kldrHlpAssert(0);
232 return rc;
233
234#elif defined(__WIN__)
235 /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
236 int rc;
237 DWORD fProt = kldrHlpPageProtToNative(enmProt);
238
239 if (!g_SystemInfo.dwPageSize)
240 GetSystemInfo(&g_SystemInfo);
241
242 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
243 if (*ppv != NULL)
244 return 0;
245 rc = GetLastError();
246 kldrHlpAssert(0);
247 return rc;
248
249#else
250# error "port me"
251#endif
252}
253
254
255/**
256 * Change the protection of one or more pages in an allocation.
257 *
258 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
259 *
260 * @returns 0 on success, non-zero OS status code on failure.
261 * @param pv First page. Page aligned.
262 * @param cb Number of bytes. Page aligned.
263 * @param enmProt The new protection. Copy-on-write is invalid.
264 */
265int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
266{
267#ifdef __OS2__
268 APIRET rc;
269 uintptr_t offStub;
270 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
271
272 /*
273 * The non-stub pages.
274 */
275 rc = DosSetMem(pv, cb, fFlags);
276 if (rc && fFlags != PAG_DECOMMIT)
277 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
278 if (rc)
279 {
280 /* Try page by page. */
281 while (cb > 0)
282 {
283 rc = DosSetMem(pv, 0x1000, fFlags);
284 if (rc && fFlags != PAG_DECOMMIT)
285 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
286 if (rc)
287 return rc;
288 pv = (void *)((uintptr_t)pv + 0x1000);
289 cb -= 0x1000;
290 }
291 }
292 kldrHlpAssert(!rc);
293 return rc;
294
295#elif defined(__WIN__)
296 DWORD fOldProt = 0;
297 DWORD fProt = kldrHlpPageProtToNative(enmProt);
298 int rc = 0;
299
300 if (!VirtualProtect(pv, cb, fProt, &fOldProt))
301 {
302 rc = GetLastError();
303 kldrHlpAssert(0);
304 }
305 return rc;
306#else
307# error "port me"
308#endif
309}
310
311
312/**
313 * Free memory allocated by kldrHlpPageAlloc().
314 *
315 * @returns 0 on success, non-zero OS status code on failure.
316 * @param pv The address returned by kldrHlpPageAlloc().
317 * @param cb The byte count requested from kldrHlpPageAlloc().
318 */
319int kldrHlpPageFree(void *pv, size_t cb)
320{
321#ifdef __OS2__
322 APIRET rc;
323
324 /*
325 * Deal with any portion overlapping with the stub.
326 */
327 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
328 if (offStub < g_cbStub)
329 {
330 /* decommit the pages in the stub. */
331 size_t cbSub = KLDR_MIN(g_cbStub - offStub, cb);
332 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
333 if (rc)
334 {
335 /* Page by page, ignoring errors after the first success. */
336 while (cbSub > 0)
337 {
338 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
339 rc = 0;
340 pv = (void *)((uintptr_t)pv + 0x1000);
341 cbSub -= 0x1000;
342 cb -= 0x1000;
343 }
344 if (rc)
345 {
346 kldrHlpAssert(!rc);
347 return rc;
348 }
349 }
350 else
351 {
352 cb -= cbSub;
353 if (!cb)
354 return 0;
355 pv = (void *)((uintptr_t)pv + cbSub);
356 }
357 }
358
359 /*
360 * Free the object.
361 */
362 rc = DosFreeMem(pv);
363 kldrHlpAssert(!rc);
364 return rc;
365
366#elif defined(__WIN__)
367 /*
368 * Free the object.
369 */
370 int rc = 0;
371 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
372 {
373 rc = GetLastError();
374 kldrHlpAssert(0);
375 }
376 return rc;
377
378#else
379# error "port me"
380#endif
381}
382
383
384/**
385 * Get an environment variable.
386 *
387 * @returns 0 on success.
388 * @returns KLDR_ERR_BUFFER_OVERFLOW on if the buffer is too small.
389 * @returns KLDR_ERR_SYMBOL_NOT_FOUND if not found. (Yeah, abusing the status code, but it's only internally...)
390 * @returns OS specfic status code on other error.
391 * @param pszVar The variable name.
392 * @param pszVal Where to store the value.
393 * @param cchVal The size of the buffer pointed to by pszVal.
394 */
395int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t cchVal)
396{
397#ifdef __OS2__
398 PSZ pszValue = NULL;
399 int rc;
400
401 *pszVal = '\0';
402 rc = DosScanEnv((PCSZ)pszVar, &pszValue);
403 if (!rc)
404 {
405 size_t cch = kLdrHlpStrLen(pszValue);
406 if (cchVal > cch)
407 kLdrHlpMemCopy(pszVal, pszValue, cch + 1);
408 else
409 rc = KLDR_ERR_BUFFER_OVERFLOW;
410 }
411 else
412 rc = KLDR_ERR_SYMBOL_NOT_FOUND;
413 return rc;
414
415#elif defined(__WIN__)
416 DWORD cch;
417
418 SetLastError(0);
419 cch = GetEnvironmentVariable(pszVar, pszVal, cchVal);
420 if (cch > 0 && cch < cchVal)
421 return 0;
422
423 *pszVal = '\0';
424 if (cch >= cchVal)
425 return KLDR_ERR_BUFFER_OVERFLOW;
426 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
427 return KLDR_ERR_SYMBOL_NOT_FOUND;
428 return GetLastError();
429
430#else
431# error "Port me"
432#endif
433}
434
435
436/**
437 * Gets an environment variable and converts it to a size_t.
438 *
439 * @returns 0 and *pcb on success.
440 * @returns On failure see kldrHlpGetEnv.
441 * @param pszVar The name of the variable.
442 * @param pcb Where to put the value.
443 */
444int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb)
445{
446 size_t cb;
447 unsigned uBase;
448 char szVal[64];
449 size_t cchVal = sizeof(szVal);
450 const char *psz;
451 int rc;
452
453 *pcb = 0;
454 rc = kldrHlpGetEnv(pszVar, szVal, cchVal);
455 if (rc)
456 return rc;
457
458 /* figure out the base. */
459 uBase = 10;
460 psz = szVal;
461 if ( *psz == '0'
462 && (psz[1] == 'x' || psz[1] == 'X'))
463 {
464 uBase = 16;
465 psz += 2;
466 }
467
468 /* convert it up to the first unknown char. */
469 cb = 0;
470 for(;;)
471 {
472 const char ch = *psz;
473 unsigned uDigit;
474 if (!ch)
475 break;
476 else if (ch >= '0' && ch <= '9')
477 uDigit = ch - '0';
478 else if (ch >= 'a' && ch <= 'z')
479 uDigit = ch - 'a' + 10;
480 else if (ch >= 'A' && ch <= 'Z')
481 uDigit = ch - 'A' + 10;
482 else
483 break;
484 if (uDigit >= uBase)
485 break;
486
487 /* add the digit */
488 cb *= uBase;
489 cb += uDigit;
490
491 psz++;
492 }
493
494 /* check for unit */
495 if (*psz == 'm' || *psz == 'M')
496 cb *= 1024*1024;
497 else if (*psz == 'k' ||*psz == 'K')
498 cb *= 1024;
499 else if (*psz == 'g' || *psz == 'G')
500 cb *= 1024*1024*1024;
501
502 *pcb = cb;
503 return 0;
504}
505
506
507/**
508 * Get the pointer to the filename part of the name.
509 *
510 * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
511 * @returns Pointer to the terminator char if no filename.
512 * @param pszFilename The filename to parse.
513 */
514char *kldrHlpGetFilename(const char *pszFilename)
515{
516 const char *pszLast = NULL;
517 for (;;)
518 {
519 char ch = *pszFilename;
520#if defined(__OS2__) || defined(__WIN__)
521 if (ch == '/' || ch == '\\' || ch == ':')
522 {
523 while ((ch = *++pszFilename) == '/' || ch == '\\' || ch == ':')
524 /* nothing */;
525 pszLast = pszFilename;
526 }
527#else
528 if (ch == '/')
529 {
530 while ((ch = *++pszFilename) == '/')
531 /* betsuni */;
532 pszLast = pszFilename;
533 }
534#endif
535 if (!ch)
536 return (char *)(pszLast ? pszLast : pszFilename);
537 pszFilename++;
538 }
539}
540
541
542/**
543 * Gets the filename suffix.
544 *
545 * @returns Pointer to where the suffix starts within the string pointed to by pszFilename.
546 * @returns Pointer to the terminator char if no suffix.
547 * @param pszFilename The filename to parse.
548 */
549char *kldrHlpGetSuff(const char *pszFilename)
550{
551 const char *pszDot = NULL;
552 pszFilename = kldrHlpGetFilename(pszFilename);
553 for (;;)
554 {
555 char ch = *pszFilename;
556 if (ch == '.')
557 {
558 while ((ch = *++pszFilename) == '.')
559 /* nothing */;
560 if (ch)
561 pszDot = pszFilename - 1;
562 }
563 if (!ch)
564 return (char *)(pszDot ? pszDot : pszFilename);
565 pszFilename++;
566 }
567}
568
569
570/**
571 * Gets the filename extention.
572 *
573 * @returns Pointer to where the extension starts within the string pointed to by pszFilename.
574 * @returns Pointer to the terminator char if no extension.
575 * @param pszFilename The filename to parse.
576 */
577char *kldrHlpGetExt(const char *pszFilename)
578{
579 char *psz = kldrHlpGetSuff(pszFilename);
580 return *psz ? psz + 1 : psz;
581}
582
583
584/**
585 * Checks if this is only a filename or if it contains any kind
586 * of drive, directory, or server specs.
587 *
588 * @returns 1 if this is a filename only.
589 * @returns 0 of it's isn't only a filename.
590 * @param pszFilename The filename to parse.
591 */
592int kldrHlpIsFilenameOnly(const char *pszFilename)
593{
594 const char *pszLast = NULL;
595 for (;;)
596 {
597 const char ch = *pszFilename++;
598#if defined(__OS2__) || defined(__WIN__)
599 if (ch == '/' || ch == '\\' || ch == ':')
600#else
601 if (ch == '/')
602#endif
603 return 0;
604 if (!ch)
605 return 1;
606 }
607}
608
609
610/**
611 * Terminate the process.
612 *
613 * @param rc The exit status.
614 */
615void kldrHlpExit(int rc)
616{
617 for (;;)
618 {
619#ifdef __OS2__
620 DosExit(EXIT_PROCESS, rc);
621
622#elif defined(__WIN__)
623 TerminateProcess(GetCurrentProcess(), rc);
624
625#else
626# error "Port me"
627#endif
628 kldrHlpAssert(!"Impossible");
629 }
630}
631
632
633/**
634 * Sleep for a number of milliseconds.
635 * @param cMillies Number of milliseconds to sleep.
636 */
637void kldrHlpSleep(unsigned cMillies)
638{
639#ifdef __OS2__
640 DosSleep(cMillies);
641#elif defined(__WIN__)
642 Sleep(cMillies);
643#else
644 usleep(cMillies * 1000);
645#endif
646}
647
648
649/**
650 * Converts an signed integer to an ascii string.
651 *
652 * @returns psz.
653 * @param psz Pointer to the output buffer.
654 * @param cch The size of the output buffer.
655 * @param lVal The value.
656 * @param iBase The base to format it. (2,8,10 or 16)
657 */
658char *kldrHlpInt2Ascii(char *psz, size_t cch, long lVal, unsigned iBase)
659{
660 static const char s_szDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
661 char *pszRet = psz;
662
663 if (cch >= (lVal < 0 ? 3U : 2U) && psz)
664 {
665 /* prefix */
666 if (lVal < 0)
667 {
668 *psz++ = '-';
669 cch--;
670 lVal = -lVal;
671 }
672
673 /* the digits */
674 do
675 {
676 *psz++ = s_szDigits[lVal % iBase];
677 cch--;
678 lVal /= iBase;
679 } while (lVal && cch > 1);
680
681 /* overflow indicator */
682 if (lVal)
683 psz[-1] = '+';
684 }
685 else if (!pszRet)
686 return pszRet;
687 else if (cch < 1 || !pszRet)
688 return pszRet;
689 else
690 *psz++ = '+';
691 *psz = '\0';
692
693 return pszRet;
694}
695
696
697/**
698 * Writes a assert string with unix lineendings.
699 *
700 * @param pszMsg The string.
701 */
702static void kldrHlpAssertWrite(const char *pszMsg)
703{
704#if defined(__OS2__) || defined(__WIN__)
705 /*
706 * Line by line.
707 */
708 ULONG cbWritten;
709 const char *pszNl = kLdrHlpStrChr(pszMsg, '\n');
710 while (pszNl)
711 {
712 cbWritten = pszNl - pszMsg;
713
714#ifdef __OS2__
715 if (cbWritten)
716 DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
717 DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
718#else /* __WIN32__ */
719 if (cbWritten)
720 WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
721 WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
722#endif
723
724 /* next */
725 pszMsg = pszNl + 1;
726 pszNl = kLdrHlpStrChr(pszMsg, '\n');
727 }
728
729 /*
730 * Remaining incomplete line.
731 */
732 if (*pszMsg)
733 {
734 cbWritten = kLdrHlpStrLen(pszMsg);
735#ifdef __OS2__
736 DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
737#else /* __WIN32__ */
738 WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
739#endif
740 }
741
742#else
743# error "port me"
744#endif
745}
746
747
748/**
749 * Internal worker for the kLdrHlpAssert() macro.
750 *
751 * @param pszExpr The assert expression.
752 * @param pszFile The filename.
753 * @param iLine The line number.
754 * @param pszFunction The function name.
755 */
756void kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
757{
758 char szLine[16];
759
760 kldrHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
761 kldrHlpAssertWrite(pszExpr);
762 kldrHlpAssertWrite("\nAt: ");
763 kldrHlpAssertWrite(pszFile);
764 kldrHlpAssertWrite("(");
765 kldrHlpAssertWrite(kldrHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
766 kldrHlpAssertWrite(") ");
767 kldrHlpAssertWrite(pszFunction);
768 kldrHlpAssertWrite("\n");
769}
770
771
772#ifdef kLdrHlpStrChr_needed
773char *kLdrHlpStrChr(const char *psz, int ch)
774{
775 while (*psz)
776 {
777 if (*psz == ch)
778 return (char *)psz;
779 psz++;
780 }
781 return NULL;
782}
783#endif
784
785
786#ifdef kLdrHlpMemChr_needed
787void *kLdrHlpMemChr(const void *pv, int ch, size_t cb)
788{
789 const uint8_t *pb = (const uint8_t *)pv;
790 const uint8_t b = (uint8_t)ch;
791 while (cb-- > 0)
792 {
793 if (*pb == b)
794 return (void *)pb;
795 pb++;
796 }
797 return NULL;
798}
799#endif
800
801
802#ifdef kLdrHlpMemMove_needed
803void *kLdrHlpMemMove(void *pv1, const void *pv2, size_t cb)
804{
805 uint8_t *pbDst = (uint8_t *)pv1;
806 const uint8_t *pbSrc = (const uint8_t *)pv2;
807 while (cb-- > 0)
808 {
809 const uint8_t b = *pbSrc++;
810 *pbDst++ = b;
811 }
812 return pv1;
813}
814#endif
815
816
817int kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb)
818{
819 const uint8_t *pb1 = (const uint8_t *)pv1;
820 const uint8_t *pb2 = (const uint8_t *)pv2;
821 while (cb-- > 0)
822 {
823 if (*pb1 != *pb2)
824 {
825 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
826 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
827 if (u1 != u2)
828 return (int)*pb1 - (int)*pb2;
829 }
830 pb1++;
831 pb2++;
832 }
833 return 0;
834}
835
836
837int kLdrHlpStrIComp(const char *pv1, const char *pv2)
838{
839 const uint8_t *pb1 = (const uint8_t *)pv1;
840 const uint8_t *pb2 = (const uint8_t *)pv2;
841 for (;;)
842 {
843 if (*pb1 != *pb2)
844 {
845 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
846 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
847 if (u1 != u2)
848 return (int)*pb1 - (int)*pb2;
849 }
850 if (!*pb1)
851 break;
852 pb1++;
853 pb2++;
854 }
855 return 0;
856}
857
Note: See TracBrowser for help on using the repository browser.