blob: c5dd2226567b3345d7d7f0c0ebd194844422c975 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
**************************************************************************
*
* File: NAString2.C
* Description: Utility string functions that can be run ONLY in a TRUSTED .exe
* Language: C++
*
*
**************************************************************************
*/
#include "Platform.h"
//#include "BaseTypes.h"
#include "ComAnsiNamePart.h"
#include "ComASSERT.h"
#include "ComRtUtils.h"
//#include "ComSmallDefs.h"
#include "str.h"
#include "NABasicObject.h"
#include "ComSizeDefs.h"
#include "NAWinNT.h"
#include "NAString.h"
#include "nawstring.h"
#include "sqlcli.h"
// move this method to NAString.h later.
NABoolean setMPLoc();
// -----------------------------------------------------------------------
static NABoolean NAString2_isUpper(unsigned char c,
SQLCHARSET_CODE isoMapCS)
{
{
return isUpper8859_1((NAWchar)c);
}
return FALSE; // dead code
}
// -----------------------------------------------------------------------
static NABoolean NAString2_isRegularStart(unsigned char c,
SQLCHARSET_CODE isoMapCS)
{
if (NAString2_isUpper(c, isoMapCS))
return TRUE;
if (isoMapCS == SQLCHARSETCODE_ISO88591 AND
isCaseInsensitive8859_1((NAWchar)c))
{
return TRUE;
}
return FALSE;
}
// -----------------------------------------------------------------------
static NABoolean NAString2_isRegular(unsigned char c,
SQLCHARSET_CODE isoMapCS)
{
if (NAString2_isRegularStart(c, isoMapCS))
return TRUE;
if (isDigit8859_1((NAWchar)c) OR c == '_')
return TRUE;
return FALSE;
}
// -----------------------------------------------------------------------
// callers to this method must make sure that nsData points to a
// valid string with length greater than 0.
char * ToAnsiIdentifier2(const char * nsData, size_t nsLen,
CollHeap * heap)
{
return ToAnsiIdentifier2(nsData, nsLen, heap, ComRtGetIsoMappingEnum());
}
// -----------------------------------------------------------------------
char * ToAnsiIdentifier2(const char * nsData, size_t nsLen,
CollHeap * heap, Lng32 isoMapCS)
{
const Int32 SMAX=2048; // See ToAnsiIdentifier for explanation of this const.
if ((nsData == NULL) || (nsLen == 0) || (nsLen > SMAX))
return NULL;
char buf[SMAX];
size_t len;
ToAnsiIdentifier3 (nsData, nsLen, buf, SMAX, &len, isoMapCS);
if (!len)
return NULL;
char * retBuf = new(heap) char[len + 1];
str_cpy_all(retBuf, buf, len);
retBuf[len] = 0;
return retBuf;
} // ToAnsiIdentifier2
// -----------------------------------------------------------------------
// In contrast to ToAnsiIdentifier2, the caller must
// pass in an output buffer of sufficient size
void ToAnsiIdentifier3(const char * inputData, size_t inputLen,
char * outputData, size_t outputMaxLen, size_t * outputLen)
{
ToAnsiIdentifier3(inputData,inputLen, /* ComGetNameInterfaceCharSet(), */
outputData, outputMaxLen, outputLen,
ComRtGetIsoMappingEnum());
}
// -----------------------------------------------------------------------
void ToAnsiIdentifier3(const char * inputData, size_t inputLen,
char * outputData, size_t outputMaxLen,
size_t * outputLen, Lng32 isoMapCS)
{
const Int32 SMAX=2048; // See ToAnsiIdentifier for explanation of this const.
if ((inputData == NULL) || (inputLen == 0) || (inputLen > SMAX) || (outputMaxLen < inputLen))
{
*outputLen = 0;
return;
}
// Fix for Bugzilla 2319 - BEGIN
//
// MXOSRVR calls CLI routines that may pass a name with trailing space(s) to the
// CatMapAnsiNameToGuardianName() routine call which indirectly calls this routine.
// Exclude the unwanted trailing spaces in inputData from the count.
//
Int32 j = (Int32)inputLen - 1;
if (j >= 0 && isSpace8859_1((unsigned char)inputData[j])) // found a trailing space
{
for (j--; j >= 0 && isSpace8859_1((unsigned char)inputData[j]); j--)
; // scan backward until a non-blank character is found
if (j + 1 <= 0) // inputData contains space(s) only
{
*outputLen = 0;
return;
}
inputLen = (size_t)(j + 1); // exclude trailing spaces from the count
}
// Fix for Bugzilla 2319 - END
char buf[SMAX];
char *bptr = &buf[1];
const char *sptr = inputData;
NABoolean isMPLoc = FALSE;
NABoolean delimited = FALSE;
SQLCHARSET_CODE isoMappingCS = (SQLCHARSET_CODE)isoMapCS;
// For SQL/MP tables (NAMETYPE NSK), the user may input a qualified NSK name
// such as \\SYS.$VOL.SUB.TBL or $VOL.SUB.TBL.
// SHORTANSI names can be internally resolved to *fully-qualified* NSK names
// that is \\SYS.$VOL.SUB.TBL only.
// NAMETYPE ANSI follows Ansi rules, disallowing '\\' and '$' in identifiers.
//
if (*sptr == '\\') {
if (setMPLoc())
isMPLoc = TRUE;
}
else if (*sptr == '$') {
if (setMPLoc())
isMPLoc = TRUE;
}
if (!isMPLoc) {
// begins with invalid char?
delimited = NOT (NAString2_isRegularStart((unsigned char)*sptr,
isoMappingCS));
}
size_t len = inputLen;
for (size_t i = 0; i < len; i++) {
if (!isMPLoc) {
if (NOT (NAString2_isRegular((unsigned char)*sptr, isoMappingCS))) {
delimited = TRUE;
if (*sptr == '\"') *bptr++ = '\"'; // this will double the dquote"
}
}
*bptr++ = *sptr++; // (with this line, that is)
}
if (delimited) {
// Verify that trailing blanks were excluded
sptr--;
if (isSpace8859_1((unsigned char)*sptr)) {
ComASSERT(0); // Note: no-op in Release build.
*outputLen = 0; // sorry, this is not supposed to happen
return;
}
}
else {
*bptr = '\0';
if (!isMPLoc && IsSqlReservedWord(buf+1))
delimited = TRUE;
} // extra checking to determine delimited state is now done
if (delimited) {
buf[0] = '\"'; // "
*bptr++ = '\"'; // "
*bptr = '\0';
bptr = &buf[0];
} else {
// *bptr = '\0'; //already done above
bptr = &buf[1];
}
len = str_len(bptr);
if ((len+1) > outputMaxLen)
{
// sorry, not enough room for the converted identifier
*outputLen = 0;
return;
}
// copy the converted identifier to the output
str_cpy_all(outputData, bptr, len);
outputData[len] = 0;
*outputLen = len;
} // ToAnsiIdentifier3
// -----------------------------------------------------------------------
// Remove whitespace (spaces and tabs) from front or back or both
// -----------------------------------------------------------------------
void TrimNAStringSpace(NAString& ns, NABoolean leading, NABoolean trailing)
{
StringPos i;
if (trailing)
if (i = ns.length()) { // assign followed by compare
for ( ; i--; )
if (!isSpace8859_1((unsigned char)ns[i]))
break;
ns.remove(++i);
}
if (leading) {
for (i=0; i<ns.length(); i++)
if (!isSpace8859_1((unsigned char)ns[i]))
break;
if (i)
ns.remove(0, i);
}
}
size_t IndexOfFirstWhiteSpace(const NAString &ns, size_t startPos)
{
for (size_t i=startPos; i<ns.length(); i++)
if (isSpace8859_1((unsigned char)ns[i]))
return i;
return NA_NPOS;
}
size_t IndexOfFirstNonWhiteSpace(const NAString &ns, size_t startPos)
{
for (size_t i=startPos; i<ns.length(); i++)
if (!isSpace8859_1((unsigned char)ns[i]))
return i;
return NA_NPOS;
}
void RemoveLeadingZeros(NAString &ns)
{
StringPos i;
for (i=0; i<(ns.length()-1); i++)
if (((unsigned char)ns[i]) != '0')
break;
if (i)
ns.remove(0, i);
}
void RemoveTrailingZeros(NAString &ns)
{
StringPos i, strLen = ns.length();
if (strLen && (((unsigned char)ns[strLen-1]) == '\0')) {
i = strLen;
for ( ; i--; )
if (((unsigned char)ns[i]) != '\0')
break;
ns.remove(++i);
}
}