2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Dynamic SQL runtime support
|
|
|
|
* MODULE: hsh.c
|
|
|
|
* DESCRIPTION: Hash table and symbol manager
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include "../dsql/dsql.h"
|
|
|
|
#include "../dsql/sym.h"
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "../jrd/gds.h"
|
2003-01-16 18:47:10 +01:00
|
|
|
#include "../jrd/gds_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../dsql/alld_proto.h"
|
|
|
|
#include "../dsql/errd_proto.h"
|
|
|
|
#include "../dsql/hsh_proto.h"
|
|
|
|
#include "../jrd/sch_proto.h"
|
|
|
|
#include "../jrd/thd_proto.h"
|
|
|
|
|
|
|
|
|
|
|
|
ASSERT_FILENAME
|
2003-09-28 02:36:28 +02:00
|
|
|
const int HASH_SIZE = 211;
|
2003-02-10 14:28:35 +01:00
|
|
|
static SSHORT hash(SCHAR *, USHORT);
|
2003-09-04 23:26:15 +02:00
|
|
|
static bool remove_symbol(struct sym **, struct sym *);
|
|
|
|
static bool scompare(TEXT *, USHORT, TEXT *, USHORT);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
static SYM *hash_table;
|
|
|
|
|
|
|
|
/*
|
|
|
|
SUPERSERVER can end up with many hands in the pie, so some
|
|
|
|
protection is provided via a mutex. This ensures the integrity
|
|
|
|
of lookups, inserts and removals, and also allows teh traversing
|
|
|
|
of symbol chains for marking of relations and procedures.
|
|
|
|
Otherwise, one DSQL user won't know what the other is doing
|
|
|
|
to the same object.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
|
|
|
static MUTX_T hash_mutex;
|
|
|
|
static USHORT hash_mutex_inited = 0;
|
2003-09-28 02:36:28 +02:00
|
|
|
static inline void lock_hash()
|
|
|
|
{
|
|
|
|
THD_mutex_lock (&hash_mutex);
|
|
|
|
}
|
2003-09-29 14:43:14 +02:00
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
static inline void unlock_hash()
|
|
|
|
{
|
|
|
|
THD_mutex_unlock (&hash_mutex);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#else
|
2003-09-28 02:36:28 +02:00
|
|
|
static inline void lock_hash()
|
|
|
|
{
|
|
|
|
}
|
2003-09-29 14:43:14 +02:00
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
static inline void unlock_hash()
|
|
|
|
{
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_init
|
|
|
|
|
|
|
|
@brief create a new hash table
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void HSHD_init(void)
|
|
|
|
{
|
|
|
|
UCHAR *p;
|
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
|
|
|
if (!hash_mutex_inited) {
|
|
|
|
hash_mutex_inited = 1;
|
|
|
|
THD_mutex_init(&hash_mutex);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
p = (UCHAR *) gds__alloc(sizeof(SYM) * HASH_SIZE);
|
2001-05-23 15:26:42 +02:00
|
|
|
memset(p, 0, sizeof(SYM) * HASH_SIZE);
|
|
|
|
|
|
|
|
hash_table = (SYM *) p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEV_BUILD
|
|
|
|
|
|
|
|
#include "../jrd/ib_stdio.h"
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_debug
|
|
|
|
|
|
|
|
@brief Print out the hash table for debugging.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void HSHD_debug(void)
|
|
|
|
{
|
|
|
|
SYM collision;
|
|
|
|
SYM homptr;
|
|
|
|
SSHORT h;
|
|
|
|
|
|
|
|
/* dump each hash table entry */
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
lock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
for (h = 0; h < HASH_SIZE; h++) {
|
|
|
|
for (collision = hash_table[h]; collision;
|
|
|
|
collision = collision->sym_collision) {
|
|
|
|
/* check any homonyms first */
|
|
|
|
|
2003-04-03 03:51:03 +02:00
|
|
|
ib_fprintf(ib_stderr, "Symbol type %d: %s %p\n",
|
2001-05-23 15:26:42 +02:00
|
|
|
collision->sym_type, collision->sym_string,
|
|
|
|
collision->sym_dbb);
|
|
|
|
for (homptr = collision->sym_homonym; homptr;
|
|
|
|
homptr = homptr->sym_homonym) {
|
2003-04-03 03:51:03 +02:00
|
|
|
ib_fprintf(ib_stderr, "Homonym Symbol type %d: %s %p\n",
|
2001-05-23 15:26:42 +02:00
|
|
|
homptr->sym_type, homptr->sym_string,
|
|
|
|
homptr->sym_dbb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_fini
|
|
|
|
|
|
|
|
@brief Clear out the symbol table. All the
|
|
|
|
symbols are deallocated with their pools.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void HSHD_fini(void)
|
|
|
|
{
|
|
|
|
|
2001-05-24 16:54:26 +02:00
|
|
|
for (SSHORT i = 0; i < HASH_SIZE; i++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
hash_table[i] = NULL;
|
2001-05-24 16:54:26 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
gds__free(hash_table);
|
2001-05-23 15:26:42 +02:00
|
|
|
hash_table = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_finish
|
|
|
|
|
|
|
|
@brief Remove symbols used by a particular database.
|
|
|
|
Don't bother to release them since their pools
|
|
|
|
will be released.
|
|
|
|
|
|
|
|
|
|
|
|
@param database
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void HSHD_finish( void *database)
|
|
|
|
{
|
|
|
|
SYM *collision;
|
|
|
|
SYM *homptr;
|
|
|
|
SYM symbol;
|
|
|
|
SYM chain;
|
|
|
|
SSHORT h;
|
|
|
|
|
|
|
|
/* check each hash table entry */
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
lock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
for (h = 0; h < HASH_SIZE; h++) {
|
|
|
|
for (collision = &hash_table[h]; *collision;) {
|
|
|
|
/* check any homonyms first */
|
|
|
|
|
|
|
|
chain = *collision;
|
|
|
|
for (homptr = &chain->sym_homonym; *homptr;) {
|
|
|
|
symbol = *homptr;
|
|
|
|
if (symbol->sym_dbb == database) {
|
|
|
|
*homptr = symbol->sym_homonym;
|
|
|
|
symbol = symbol->sym_homonym;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
homptr = &symbol->sym_homonym;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now, see if the root entry has to go */
|
|
|
|
|
|
|
|
if (chain->sym_dbb == database) {
|
|
|
|
if (chain->sym_homonym) {
|
|
|
|
chain->sym_homonym->sym_collision = chain->sym_collision;
|
|
|
|
*collision = chain->sym_homonym;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*collision = chain->sym_collision;
|
|
|
|
chain = *collision;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
collision = &chain->sym_collision;
|
|
|
|
}
|
|
|
|
}
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_insert
|
|
|
|
|
|
|
|
@brief Insert a symbol into the hash table.
|
|
|
|
|
|
|
|
|
|
|
|
@param symbol
|
|
|
|
|
|
|
|
**/
|
2003-02-10 14:28:35 +01:00
|
|
|
void HSHD_insert(SYM symbol)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-02-10 14:28:35 +01:00
|
|
|
SSHORT h;
|
|
|
|
void *database;
|
|
|
|
SYM old;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
lock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
h = hash(symbol->sym_string, symbol->sym_length);
|
|
|
|
database = symbol->sym_dbb;
|
|
|
|
|
|
|
|
assert(symbol->sym_type >= SYM_statement && symbol->sym_type <= SYM_eof);
|
|
|
|
|
|
|
|
for (old = hash_table[h]; old; old = old->sym_collision)
|
|
|
|
if ((!database || (database == old->sym_dbb)) &&
|
|
|
|
scompare(symbol->sym_string, symbol->sym_length, old->sym_string,
|
2003-09-04 23:26:15 +02:00
|
|
|
old->sym_length))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
symbol->sym_homonym = old->sym_homonym;
|
|
|
|
old->sym_homonym = symbol;
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
symbol->sym_collision = hash_table[h];
|
|
|
|
hash_table[h] = symbol;
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_lookup
|
|
|
|
|
|
|
|
@brief Perform a string lookup against hash table.
|
|
|
|
Make sure to only return a symbol of the desired type.
|
|
|
|
|
|
|
|
|
|
|
|
@param database
|
|
|
|
@param string
|
|
|
|
@param length
|
|
|
|
@param type
|
|
|
|
@param parser_version
|
|
|
|
|
|
|
|
**/
|
2003-02-12 20:28:13 +01:00
|
|
|
SYM HSHD_lookup(void* database,
|
|
|
|
TEXT* string,
|
|
|
|
SSHORT length,
|
|
|
|
SYM_TYPE type,
|
|
|
|
USHORT parser_version)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
lock_hash();
|
2003-02-12 20:28:13 +01:00
|
|
|
SSHORT h = hash(string, length);
|
|
|
|
for (SYM symbol = hash_table[h]; symbol; symbol = symbol->sym_collision)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((database == symbol->sym_dbb) &&
|
2003-02-12 20:28:13 +01:00
|
|
|
scompare(string, length, symbol->sym_string, symbol->sym_length))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
/* Search for a symbol of the proper type */
|
2003-02-12 20:28:13 +01:00
|
|
|
while (symbol && symbol->sym_type != type) {
|
2001-05-23 15:26:42 +02:00
|
|
|
symbol = symbol->sym_homonym;
|
2003-02-12 20:28:13 +01:00
|
|
|
}
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* If the symbol found was not part of the list of keywords for the
|
|
|
|
* client connecting, then assume nothing was found
|
|
|
|
*/
|
2003-02-12 20:28:13 +01:00
|
|
|
if (symbol)
|
|
|
|
{
|
|
|
|
if (parser_version < symbol->sym_version &&
|
|
|
|
type == SYM_keyword)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
return symbol;
|
|
|
|
}
|
2003-02-12 20:28:13 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_remove
|
|
|
|
|
|
|
|
@brief Remove a symbol from the hash table.
|
|
|
|
|
|
|
|
|
|
|
|
@param symbol
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void HSHD_remove( SYM symbol)
|
|
|
|
{
|
|
|
|
SYM *collision;
|
|
|
|
SSHORT h;
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
lock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
h = hash(symbol->sym_string, symbol->sym_length);
|
|
|
|
|
|
|
|
for (collision = &hash_table[h]; *collision;
|
2003-09-04 23:26:15 +02:00
|
|
|
collision = &(*collision)->sym_collision)
|
|
|
|
{
|
|
|
|
if (remove_symbol(collision, symbol)) {
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
2003-09-04 23:26:15 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
IBERROR(-1, "HSHD_remove failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
HSHD_set_flag
|
|
|
|
|
|
|
|
@brief Set a flag in all similar objects in a chain. This
|
|
|
|
is used primarily to mark relations and procedures
|
|
|
|
as deleted. The object must have the same name and
|
|
|
|
type, but not the same database, and must belong to
|
|
|
|
some database. Later access to such an object by
|
|
|
|
another user or thread should result in that object's
|
|
|
|
being refreshed. Note that even if the relation name
|
|
|
|
and ID, or the procedure name and ID both match, it
|
|
|
|
may still not represent an exact match. This is because
|
|
|
|
there's no way at present for DSQL to tell if two databases
|
|
|
|
as represented in DSQL are attachments to the same physical
|
|
|
|
database.
|
|
|
|
|
|
|
|
|
|
|
|
@param database
|
|
|
|
@param string
|
|
|
|
@param length
|
|
|
|
@param type
|
|
|
|
@param flag
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void HSHD_set_flag(
|
|
|
|
void *database,
|
|
|
|
TEXT * string, SSHORT length, SYM_TYPE type, SSHORT flag)
|
|
|
|
{
|
|
|
|
SYM symbol, homonym;
|
|
|
|
SSHORT h;
|
|
|
|
DSQL_REL sym_rel;
|
2002-11-17 01:04:19 +01:00
|
|
|
DSQL_PRC sym_prc;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* as of now, there's no work to do if there is no database or if
|
|
|
|
the type is not a relation or procedure */
|
|
|
|
|
|
|
|
if (!database)
|
|
|
|
return;
|
|
|
|
switch (type) {
|
|
|
|
case SYM_relation:
|
|
|
|
case SYM_procedure:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
lock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
h = hash(string, length);
|
|
|
|
for (symbol = hash_table[h]; symbol; symbol = symbol->sym_collision) {
|
|
|
|
if (symbol->sym_dbb && (database != symbol->sym_dbb) &&
|
|
|
|
scompare(string, length, symbol->sym_string, symbol->sym_length)) {
|
|
|
|
|
|
|
|
/* the symbol name matches and it's from a different database */
|
|
|
|
|
|
|
|
for (homonym = symbol; homonym; homonym = homonym->sym_homonym) {
|
|
|
|
if (homonym->sym_type == type) {
|
|
|
|
|
|
|
|
/* the homonym is of the correct type */
|
|
|
|
|
|
|
|
/* the next check is for the same relation or procedure ID,
|
|
|
|
which indicates that it MAY be the same relation or
|
|
|
|
procedure */
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case SYM_relation:
|
|
|
|
sym_rel = (DSQL_REL) homonym->sym_object;
|
|
|
|
sym_rel->rel_flags |= flag;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SYM_procedure:
|
2002-11-17 01:04:19 +01:00
|
|
|
sym_prc = (DSQL_PRC) homonym->sym_object;
|
2001-05-23 15:26:42 +02:00
|
|
|
sym_prc->prc_flags |= flag;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-28 02:36:28 +02:00
|
|
|
unlock_hash();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
hash
|
|
|
|
|
|
|
|
@brief Returns the hash function of a string.
|
|
|
|
|
|
|
|
|
|
|
|
@param
|
|
|
|
@param
|
|
|
|
|
|
|
|
**/
|
2003-02-10 14:28:35 +01:00
|
|
|
static SSHORT hash(SCHAR * string, USHORT length)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-02-10 14:28:35 +01:00
|
|
|
SLONG value;
|
2001-05-23 15:26:42 +02:00
|
|
|
SCHAR c;
|
|
|
|
|
|
|
|
value = 0;
|
|
|
|
|
|
|
|
while (length--) {
|
|
|
|
c = *string++;
|
|
|
|
value = (value << 1) + (c);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((value >= 0) ? value : -value) % HASH_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
remove_symbol
|
|
|
|
|
|
|
|
@brief Given the address of a collision,
|
|
|
|
remove a symbol from the collision
|
|
|
|
and homonym linked lists.
|
|
|
|
|
|
|
|
|
|
|
|
@param collision
|
|
|
|
@param symbol
|
|
|
|
|
|
|
|
**/
|
2003-09-04 23:26:15 +02:00
|
|
|
static bool remove_symbol( SYM * collision, SYM symbol)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-02-10 14:28:35 +01:00
|
|
|
SYM *ptr, homonym;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (symbol == *collision) {
|
|
|
|
if ((homonym = symbol->sym_homonym) != NULL) {
|
|
|
|
homonym->sym_collision = symbol->sym_collision;
|
|
|
|
*collision = homonym;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*collision = symbol->sym_collision;
|
|
|
|
|
2003-09-04 23:26:15 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (ptr = &(*collision)->sym_homonym; *ptr; ptr = &(*ptr)->sym_homonym)
|
|
|
|
if (symbol == *ptr) {
|
|
|
|
*ptr = symbol->sym_homonym;
|
2003-09-04 23:26:15 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-09-04 23:26:15 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
scompare
|
|
|
|
|
|
|
|
@brief Compare two symbolic strings
|
|
|
|
The character set for these strings is either ASCII or
|
|
|
|
Unicode in UTF format.
|
|
|
|
Symbols are case-significant - so no uppercase operation
|
|
|
|
is performed.
|
|
|
|
|
|
|
|
|
|
|
|
@param string1
|
|
|
|
@param length1
|
|
|
|
@param string2
|
|
|
|
@param length2
|
|
|
|
|
|
|
|
**/
|
2003-09-04 23:26:15 +02:00
|
|
|
static bool scompare(TEXT * string1,
|
2003-02-10 14:28:35 +01:00
|
|
|
USHORT length1,
|
|
|
|
TEXT * string2, USHORT length2)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
if (length1 != length2)
|
2003-09-04 23:26:15 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (length1--) {
|
|
|
|
if ((*string1++) != (*string2++))
|
2003-09-04 23:26:15 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-09-04 23:26:15 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|