2 * PROJECT: ReactOS Application compatibility module
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Shim database string table builder
5 * COPYRIGHT: Copyright 2016-2019 Mark Jansen (mark.jansen@reactos.org)
8 #if !defined(SDBWRITE_HOSTTOOL)
9 #define WIN32_NO_STATUS
11 #include <appcompat/sdbtypes.h>
13 #else /* !defined(SDBWRITE_HOSTTOOL) */
18 #endif /* !defined(SDBWRITE_HOSTTOOL) */
20 #include "sdbstringtable.h"
22 #if !defined(offsetof)
24 #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
26 #define offsetof(TYPE, MEMBER) ((size_t)&(((TYPE *)0)->MEMBER))
28 #endif // !defined(offsetof)
30 #define DEFAULT_TABLE_SIZE 0x100
32 typedef struct SdbHashEntry
34 struct SdbHashEntry
* Next
;
39 struct SdbStringHashTable
42 struct SdbHashEntry
** Entries
;
46 static struct SdbStringHashTable
* HashCreate(void)
48 struct SdbStringHashTable
* tab
= SdbAlloc(sizeof(*tab
));
51 SHIM_ERR("Failed to allocate 8 bytes.\r\n");
54 tab
->Size
= DEFAULT_TABLE_SIZE
;
55 tab
->Entries
= SdbAlloc(tab
->Size
* sizeof(*tab
->Entries
));
60 void SdbpTableDestroy(struct SdbStringHashTable
** pTable
)
62 struct SdbStringHashTable
* table
= *pTable
;
63 struct SdbHashEntry
* entry
, *next
;
64 DWORD n
, depth
= 0, once
= 1;
67 for (n
= 0; n
< table
->Size
; ++n
)
70 entry
= next
= table
->Entries
[n
];
78 if (once
&& depth
> 3)
84 SdbFree(table
->Entries
);
88 /* Based on RtlHashUnicodeString */
89 static DWORD
StringHash(const WCHAR
* str
)
94 hash
= ((65599 * hash
) + (ULONG
)(*str
));
99 int Sdbwcscmp(const WCHAR
* s1
, const WCHAR
* s2
)
112 // implementation taken from reactos/sdk/lib/crt/string/wcs.c
113 INT
Sdbwcscpy(WCHAR
* wcDest
, size_t numElement
, const WCHAR
*wcSrc
)
116 if(!wcDest
|| !numElement
)
117 return 22; /* EINVAL */
122 return 22; /* EINVAL */
124 size
= SdbpStrlen(wcSrc
) + 1;
126 if(size
> numElement
)
127 return 34; /* ERANGE */
129 memcpy(wcDest
, wcSrc
, size
* sizeof(WCHAR
));
134 static struct SdbHashEntry
** TableFindPtr(struct SdbStringHashTable
* table
, const WCHAR
* str
)
136 DWORD hash
= StringHash(str
);
137 struct SdbHashEntry
** entry
= &table
->Entries
[hash
% table
->Size
];
140 if (!Sdbwcscmp((*entry
)->Name
, str
))
142 entry
= &(*entry
)->Next
;
147 static BOOL
HashAddString(struct SdbStringHashTable
* table
, struct SdbHashEntry
** position
, const WCHAR
* str
, TAGID tagid
)
149 struct SdbHashEntry
* entry
;
153 position
= TableFindPtr(table
, str
);
155 len
= SdbpStrlen(str
) + 1;
156 size
= offsetof(struct SdbHashEntry
, Name
[len
]);
157 entry
= (*position
) = SdbAlloc(size
);
160 SHIM_ERR("Failed to allocate %u bytes.", size
);
163 entry
->Tagid
= tagid
;
164 Sdbwcscpy(entry
->Name
, len
, str
);
169 BOOL
SdbpAddStringToTable(struct SdbStringHashTable
** table
, const WCHAR
* str
, TAGID
* tagid
)
171 struct SdbHashEntry
** entry
;
175 *table
= HashCreate();
178 SHIM_ERR("Error creating hash table\n");
183 entry
= TableFindPtr(*table
, str
);
186 *tagid
= (*entry
)->Tagid
;
189 return HashAddString(*table
, entry
, str
, *tagid
);