//+------------------------------------------------------------------ // // File: culong.cxx // // Contents: implementation for CUlongCmdlineObj // // Synoposis: Encapsulates a command line switch which takes an // unsigned long value, eg: /maxusers:10 // // Classes: CUlongCmdlineObj // // Functions: // // History: 06/15/92 DeanE Stolen from CIntCmdlineObj code // 07/29/92 davey Added nlsType and nlsLineArgType // 09/09/92 Lizch Changed SUCCESS to NO_ERROR // 09/18/92 Lizch Precompile headers // 11/14/92 DwightKr Updates for new version of NLS_STR // 10/14/93 DeanE Converted to NCHAR // //------------------------------------------------------------------- #include #pragma hdrstop #include // public cmdlinew stuff #include "_clw.hxx" // private cmdlinew stuff #include // is functions INT StringToUlong(LPCNSTR pnszInt, ULONG *pUlong); LPCNSTR nszCmdlineUlong = _TEXTN("Takes an unsigned long "); LPCNSTR nszLineArgUlong = _TEXTN(" "); //+------------------------------------------------------------------ // // Member: CUlongCmdlineObj destructor // // Synoposis: Frees any memory associated with the object // // History: Added to allow casting of pValue 05/12/92 Lizch // Integrated into CUlongCmdlineObj 6/15/92 DeanE // //------------------------------------------------------------------- CUlongCmdlineObj::~CUlongCmdlineObj() { delete (ULONG *)_pValue; _pValue = NULL; } //+------------------------------------------------------------------ // // Member: CUlongCmdlineObj::SetValue, public // // Synposis: Stores the ulong value specified after the switch // string, eg. 10 for /maxusers:10 // // Effects: This implementation for the virtual method SetValue // converts the characters following the switch to an unsigned // long. It allocates memory for the ulong. // If there is no equator character, or if there // is no character following the equator character, _pValue // remains NULL. // // Arguments: [nszArg] - the string following the switch on the // command line. Includes the equator (eg. // ':' or '=' ), if any. // // Returns: CMDLINE_NO_ERROR, CMDLINE_ERROR_OUT_OF_MEMORY, // CMDLINE_ERROR_TOO_BIG, CMDLINE_ERROR_INVALID_VALUE // // History: Created 12/27/91 Lizch // Converted to NLS_STR 4/17/92 Lizch // Integrated into CUlongCmdlineObj 6/15/92 DeanE // //------------------------------------------------------------------- INT CUlongCmdlineObj::SetValue(LPCNSTR nszArg) { INT iRC; // delete any existing _pValue delete (ULONG *)_pValue; _pValue = NULL; _pValue = new ULONG; if (_pValue == NULL) { return (CMDLINE_ERROR_OUT_OF_MEMORY); } // I'm using this rather than c runtime atol so that I // can detect error conditions like overflow and non-digits. iRC = StringToUlong(nszArg, (ULONG *)_pValue); if (iRC != CMDLINE_NO_ERROR) { delete (ULONG *)_pValue; _pValue = NULL; } return(iRC); } //+------------------------------------------------------------------ // // Member: CUlongCmdlineObj::GetValue, public // // Synposis: Returns a pointer to ULONG that holds the value. // // Arguments: void // // Returns: ULONG value at *_pValue. // // History: Created 12/27/91 Lizch // Converted to NLS_STR 4/17/92 Lizch // Integrated into CUlongCmdlineObj 6/15/92 DeanE // //------------------------------------------------------------------- const ULONG *CUlongCmdlineObj::GetValue() { return((ULONG *)_pValue); } //+------------------------------------------------------------------ // // Member: CUlongCmdlineObj::DisplayValue, public // // Synoposis: Prints the stored command line value accordint to // current display method. Generally this will be to stdout. // // History: Created 12/27/91 Lizch // Converted to NLS_STR 4/17/92 Lizch // Integrated into CUlongCmdlineObj 6/15/92 DeanE // //------------------------------------------------------------------- void CUlongCmdlineObj::DisplayValue() { if (_pValue != NULL) { _sNprintf(_nszErrorBuf, _TEXTN("Command line switch %s has value %lu\n"), _pnszSwitch, *(ULONG *)_pValue); (*_pfnDisplay)(_nszErrorBuf); } else { DisplayNoValue(); } } //+------------------------------------------------------------------ // // Function: StringToUlong // // Synoposis: Converts given string to unsigned long, checking for // overflow and illegal characters. Only +, - and digits // are accepted. // // Arguments: [nszUlong] - string to convert // [pUlong] - pointer to converted unsigned long // // Returns: CMDLINE_NO_ERROR, CMDLINE_ERROR_INVALID_VALUE, // CMDLINE_ERROR_TOO_BIG // // History: Created 12/17/91 Lizch // Converted to AsciiToUlong 6/15/92 DeanE // Added in conversion of Hex 12/27/94 DaveY // // Notes: I'm using this rather than c runtime atoi so that I // can detect error conditions like overflow and non-digits. // The sign is checked for and stored, although it is not // used - so a negative value will still be converted to // an unsigned equivalent. // //------------------------------------------------------------------- INT StringToUlong(LPCNSTR nszUlong, ULONG *pUlong) { short sNegator = 1; ULONG ulResult = 0; INT iRC = CMDLINE_NO_ERROR; // Skip any leading spaces - these can occur if the command line // switch incorporates spaces, eg "/a: 123" // while (_isnspace(*nszUlong)) { nszUlong++; } // Get sign - ignore for now switch (*nszUlong) { case '-': sNegator = -1; nszUlong++; break; case '+': sNegator = 1; nszUlong++; break; default: break; } // see if using hex values if ((*nszUlong == _TEXTN('0')) && ((*(nszUlong+1) == _TEXTN('x')) || (*(nszUlong+1) == _TEXTN('X')))) { nszUlong += 2; // pass the "0x" int max = sizeof(ULONG) << 1; // number of hex digits possible for(int i=0; *nszUlong != NULL && i < max; i++, nszUlong++) { if ((_TEXTN('0') <= *nszUlong ) && (*nszUlong <= _TEXTN('9'))) { ulResult = ulResult * 16 + (*nszUlong - _TEXTN('0')); } else if ((_TEXTN('A') <= *nszUlong ) && (*nszUlong <= _TEXTN('F'))) { ulResult = ulResult * 16 + 10 + (*nszUlong - _TEXTN('A')); } else if ((_TEXTN('a') <= *nszUlong) && (*nszUlong <= _TEXTN('f'))) { ulResult = ulResult * 16 + 10 + (*nszUlong - _TEXTN('a')); } else { iRC = CMDLINE_ERROR_INVALID_VALUE; ulResult = 0; break; } } if ((i >= max) && (*nszUlong != NULL)) { iRC = CMDLINE_ERROR_INVALID_VALUE; ulResult = 0; } *pUlong = ulResult; return iRC; } // must be decimal for (;*nszUlong != L'\0'; nszUlong++) { if (!_isndigit(*nszUlong)) { ulResult = 0; iRC = CMDLINE_ERROR_INVALID_VALUE; break; } ULONG ulPrevious = ulResult; ulResult = (ulResult * 10) + (*nszUlong - '0'); // Check for overflow by checking that the previous result is less // than the current result - if the previous one was bigger, we've // overflowed! // if (ulResult < ulPrevious) { ulResult = 0; iRC = CMDLINE_ERROR_TOO_BIG; break; } } *pUlong = ulResult; return(iRC); } //+------------------------------------------------------------------- // // Method: CUlongCmdlineObj::QueryCmdlineType, protected, const // // Synoposis: returns a character pointer to the cmdline type. // // Arguments: None. // // Returns: const NCHAR pointer to string. // // History: 28-Jul-92 davey Created. // //-------------------------------------------------------------------- LPCNSTR CUlongCmdlineObj::QueryCmdlineType() const { return(nszCmdlineUlong); } //+------------------------------------------------------------------- // // Method: CUlongCmdlineObj::QueryLineArgType, protected, const // // Synoposis: returns a character pointer to the line arg type. // // Arguments: None. // // Returns: const NLS_STR reference to string. // // History: 28-Jul-92 davey Created. // //-------------------------------------------------------------------- LPCNSTR CUlongCmdlineObj::QueryLineArgType() const { // if user has not defined one then give default one if (_pnszLineArgType == NULL) { return(nszLineArgUlong); } else { return(_pnszLineArgType); } }