625 lines
10 KiB
C++
625 lines
10 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
SUB_STRING
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the definition of the SUB_STRING class.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
ULIB, User Mode
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
A substring is a subsequence of characters taken from a "base"
|
|||
|
string. Substrings are useful in those cases in which we want
|
|||
|
to operate on "chunks" of a given string (e.g. parsing), without
|
|||
|
having to create separate strings for each one.
|
|||
|
|
|||
|
One must be careful when using substrings, though. Since
|
|||
|
substrings depend on a base string, the base string must exist
|
|||
|
during the life span of all its substrings. In other words,
|
|||
|
the base string must not be deleted before having deleted all
|
|||
|
the substrings obtained from it.
|
|||
|
|
|||
|
Note that GENERIC_STRINGs have no substring support. It is up to
|
|||
|
the derived string classes to provide it.
|
|||
|
|
|||
|
Since substrings are just "windows" into a base string, any
|
|||
|
modification of a substring will be reflected in the base
|
|||
|
string (hence in all other substrings). This is why we have
|
|||
|
two classes of substrings:
|
|||
|
|
|||
|
SUB_STRING allows only read operations. Note however that
|
|||
|
one can modify the base string directly.
|
|||
|
|
|||
|
DYNAMIC_SUB_STRING is derived from the above, and it allows
|
|||
|
write operations. Needless to say, you should
|
|||
|
not use this class unless you're sure of what
|
|||
|
you are doing.
|
|||
|
|
|||
|
Substring objects cannot be created and initialized directly by the
|
|||
|
user, they must be obtained thru a base string class with substring
|
|||
|
support.
|
|||
|
|
|||
|
Substrings pertaining to the same base string are chained together
|
|||
|
in a doubly-linked queue. Since substrings have no knowledge of the
|
|||
|
internals of their base string, the chain has a dummy element as its
|
|||
|
head. In order to provide substring support, the base string must
|
|||
|
follow these steps:
|
|||
|
|
|||
|
|
|||
|
1.- Before spawning any substring, the substring chain head must
|
|||
|
be created and initialized using the InitializeChainHead() method.
|
|||
|
Note that this substring is a dummy one, beknown only to the base
|
|||
|
string.
|
|||
|
|
|||
|
2.- Whenever spawning a new substring, it must be linked to the chain
|
|||
|
using the InitializeChainNode() method. Any substring already in
|
|||
|
the chain may be use as argument, but the obvious choice is the
|
|||
|
chain head.
|
|||
|
|
|||
|
3.- Each time that the size of the string changes, the Update() of the
|
|||
|
chain head must be invoked.
|
|||
|
|
|||
|
4.- Before destroying a base string, you have to make sure that all its
|
|||
|
substrings have gone away. This means that the chain head must be
|
|||
|
the only element of the chain. Use the HasLinks() method to
|
|||
|
verify this.
|
|||
|
|
|||
|
5.- Don't forget to destroy the chain head before destorying the base
|
|||
|
string.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//
|
|||
|
// This class is no longer supported
|
|||
|
//
|
|||
|
|
|||
|
#include "wstring.hxx"
|
|||
|
|
|||
|
#define _SUB_STRING_
|
|||
|
|
|||
|
#if !defined (_SUB_STRING_)
|
|||
|
|
|||
|
#define _SUB_STRING_
|
|||
|
|
|||
|
#include "string.hxx"
|
|||
|
|
|||
|
DECLARE_CLASS( SUB_STRING );
|
|||
|
|
|||
|
class SUB_STRING : public GENERIC_STRING {
|
|||
|
|
|||
|
friend SUB_STRING;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
DECLARE_CONSTRUCTOR( SUB_STRING );
|
|||
|
DECLARE_CAST_MEMBER_FUNCTION( SUB_STRING );
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
~SUB_STRING (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
HasLinks (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
InitializeChainHead (
|
|||
|
IN PGENERIC_STRING BaseString
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
InitializeChainNode (
|
|||
|
IN OUT PSUB_STRING SubString,
|
|||
|
IN CHNUM Position,
|
|||
|
IN CHNUM Length
|
|||
|
);
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
PBYTE
|
|||
|
GetInternalBuffer (
|
|||
|
IN CHNUM Position DEFAULT 0
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
BOOLEAN
|
|||
|
IsChAt (
|
|||
|
IN WCHAR Char,
|
|||
|
IN CHNUM Position DEFAULT 0
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
BOOLEAN
|
|||
|
MakeNumber (
|
|||
|
OUT PLONG Number,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
ULONG
|
|||
|
QueryByteCount (
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
WCHAR
|
|||
|
QueryChAt(
|
|||
|
IN CHNUM Position DEFAULT 0
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
QueryChCount (
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
PGENERIC_STRING
|
|||
|
QueryGenericString (
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
PSTR
|
|||
|
QuerySTR(
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END,
|
|||
|
IN OUT PSTR Buffer DEFAULT NULL,
|
|||
|
IN ULONG BufferSize DEFAULT 0
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
PSUB_STRING
|
|||
|
QuerySubString (
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END,
|
|||
|
OUT PSUB_STRING SubString DEFAULT NULL
|
|||
|
);
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
PWSTR
|
|||
|
QueryWSTR (
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END,
|
|||
|
IN OUT PWSTR Buffer DEFAULT NULL,
|
|||
|
IN ULONG BufferSize DEFAULT 0,
|
|||
|
IN BOOLEAN ForceNull DEFAULT TRUE
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
BOOLEAN
|
|||
|
Replace (
|
|||
|
IN PCGENERIC_STRING String2,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END,
|
|||
|
IN CHNUM Position2 DEFAULT 0,
|
|||
|
IN CHNUM Length2 DEFAULT TO_END
|
|||
|
);
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
BOOLEAN
|
|||
|
SetChAt (
|
|||
|
IN WCHAR Char,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
);
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
Strchr (
|
|||
|
IN WCHAR Char,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
LONG
|
|||
|
Strcmp (
|
|||
|
IN PCGENERIC_STRING GenericString
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
Strcspn (
|
|||
|
IN PCGENERIC_STRING GenericString,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
LONG
|
|||
|
Stricmp (
|
|||
|
IN PCGENERIC_STRING GenericString
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
LONG
|
|||
|
StringCompare (
|
|||
|
IN CHNUM Position1,
|
|||
|
IN CHNUM Length1,
|
|||
|
IN PCGENERIC_STRING GenericString2,
|
|||
|
IN CHNUM Position2,
|
|||
|
IN CHNUM Length2,
|
|||
|
IN USHORT CompareFlags DEFAULT COMPARE_IGNORECASE
|
|||
|
) CONST;
|
|||
|
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
StrLen (
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
Strrchr (
|
|||
|
IN WCHAR Char,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
Strspn (
|
|||
|
IN PCGENERIC_STRING GenericString,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
CHNUM
|
|||
|
Strstr (
|
|||
|
IN PCGENERIC_STRING GenericString,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
Update (
|
|||
|
IN CHNUM Length
|
|||
|
);
|
|||
|
|
|||
|
protected:
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
PGENERIC_STRING
|
|||
|
GetBaseString (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
PSUB_STRING
|
|||
|
GetNextInChain (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
PSUB_STRING
|
|||
|
GetPreviousInChain (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
GetValidLength(
|
|||
|
IN CHNUM Position,
|
|||
|
IN OUT PCHNUM Length
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
CHNUM
|
|||
|
QueryStartingPosition (
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
SetChCount(
|
|||
|
IN CHNUM NewCount
|
|||
|
);
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
Construct (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
Destroy (
|
|||
|
);
|
|||
|
|
|||
|
PGENERIC_STRING _BaseString; // base string to take substring
|
|||
|
CHNUM _StartingPosition; // starting index within base
|
|||
|
CHNUM _CountOfChars; // # of chars in substring
|
|||
|
|
|||
|
PSUB_STRING _Previous; // Previous in chain
|
|||
|
PSUB_STRING _Next; // Next in chain
|
|||
|
|
|||
|
#if DBG==1
|
|||
|
ULONG _Signature;
|
|||
|
BOOLEAN _Initialized;
|
|||
|
#endif
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
INLINE
|
|||
|
PGENERIC_STRING
|
|||
|
SUB_STRING::GetBaseString (
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Gets a pointer to the base string
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to the base string
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DebugAssert( _Initialized );
|
|||
|
return _BaseString;
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
PSUB_STRING
|
|||
|
SUB_STRING::GetNextInChain (
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Gets a pointer to next substring in the chain
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to substring
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DebugAssert( _Initialized );
|
|||
|
return _Next;
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
PSUB_STRING
|
|||
|
SUB_STRING::GetPreviousInChain (
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Gets a pointer to previous substring in the chain
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to the previous substring
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DebugAssert( _Initialized );
|
|||
|
return _Previous;
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
SUB_STRING::GetValidLength (
|
|||
|
IN CHNUM Position,
|
|||
|
IN OUT PCHNUM Length
|
|||
|
) CONST
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
If the length passed has the magic value TO_END, then it is
|
|||
|
updated to be the from the passed position up to the end of the
|
|||
|
substring.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Position - Supplies a starting position within the substring
|
|||
|
Length - Supplies a length
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
DebugAssert(_Initialized );
|
|||
|
|
|||
|
DebugAssert( Position <= _CountOfChars );
|
|||
|
|
|||
|
if ( *Length == TO_END ) {
|
|||
|
*Length = _CountOfChars - Position;
|
|||
|
}
|
|||
|
|
|||
|
DebugAssert( Position + *Length <= _CountOfChars );
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
SUB_STRING::HasLinks (
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines if the substring has forward and backward links
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the stubstring has forward or backward links
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DebugAssert( _Initialized );
|
|||
|
return ( (GetNextInChain() != NULL ) || (GetPreviousInChain() != NULL ) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
CHNUM
|
|||
|
SUB_STRING::QueryStartingPosition (
|
|||
|
) CONST
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the starting character position within the base string.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The starting character position within the base string.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DebugAssert( _Initialized );
|
|||
|
return _StartingPosition;
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
SUB_STRING::SetChCount (
|
|||
|
IN CHNUM NewCount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the number of characters in the substring
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NewCount - Supplies the new count of characters
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DebugAssert( _Initialized );
|
|||
|
_CountOfChars = NewCount;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#endif // _SUB_STRING_
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
DYNAMIC_SUB_STRING
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the definition of the DYNAMIC_SUB_STRING class.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
DYNAMIC_SUB_STRINGs can modify the base string (see notes for
|
|||
|
SUB_STRING class).
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define _DYNAMIC_SUB_STRING_
|
|||
|
|
|||
|
#if !defined (_DYNAMIC_SUB_STRING_)
|
|||
|
|
|||
|
#define _DYNAMIC_SUB_STRING_
|
|||
|
|
|||
|
DECLARE_CLASS( DYNAMIC_SUB_STRING );
|
|||
|
|
|||
|
class DYNAMIC_SUB_STRING : public SUB_STRING {
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
DECLARE_CONSTRUCTOR( DYNAMIC_SUB_STRING );
|
|||
|
DECLARE_CAST_MEMBER_FUNCTION( DYNAMIC_SUB_STRING );
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
Copy (
|
|||
|
IN PCGENERIC_STRING GenericString
|
|||
|
);
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
BOOLEAN
|
|||
|
SetChAt (
|
|||
|
IN WCHAR Char,
|
|||
|
IN CHNUM Position DEFAULT 0,
|
|||
|
IN CHNUM Length DEFAULT TO_END
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
CHNUM
|
|||
|
Truncate (
|
|||
|
IN CHNUM Position DEFAULT 0
|
|||
|
);
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
VOID
|
|||
|
Construct (
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
#endif // _DYNAMIC_SUB_STRING_
|