Here is a short 64-bit (VS2010) console application, trying to mimic a few of the PowerBASIC built-in string functions.
I have even used the trailing $ string character at the end of the PB's like function names ;D
// Test.cpp : define the enter point for console application.
#include "stdafx.h"
//
#include <windows.h> // Search along the path.
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const wchar_t *$NULL = L"";
const wchar_t *$Dot = L".";
const wchar_t *$Comma = L",";
long LongVAL(IN wstring sNum) {
long value = 0;
value = _wtol(sNum.c_str());
return value;
}
double FloatVAL(IN wstring sNum) {
double value = 0;
value = _wtof(sNum.c_str());
return value;
}
LONG_PTR INSTR(IN long nIndex, IN wstring sMain, IN wstring sSearch) {
LONG_PTR nRet = -1; // Not found
LONG_PTR nLength = sMain.length();
if (nLength && (sSearch.length())) {
if (nIndex < 0) {
nRet = sMain.find_last_of(sSearch, nLength + nIndex + 1); }
else {
nRet = sMain.find_first_of(sSearch, nIndex);
}
}
return nRet;
}
wstring zGetCTLText(IN HWND hCtrl) {
WCHAR buf[4096];
GetWindowText(hCtrl, buf, 4096);
return wstring(buf);
}
wstring UCASE$(IN wstring sBuf) {
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), ::toupper);
return sBuf;
}
wstring LCASE$(IN wstring sBuf) {
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), ::tolower);
return sBuf;
}
wstring LTRIM$(IN wstring sBuf, IN wstring sChar) {
wstring sResult = sBuf;
LONG_PTR nLength = sBuf.length();
if (nLength && (sChar.length())) {
long K = 0;
while (K < nLength) {
// This is the sChar ANY search version
if (std::wstring::npos != sChar.find(sBuf.substr(K, 1))) {
++K; }
else {
break;
}
}
sResult = sBuf.substr(K, nLength);
}
return sResult;
}
wstring RTRIM$(IN wstring sBuf, IN wstring sChar) {
wstring sResult = sBuf;
LONG_PTR nLength = sBuf.length();
if (nLength && (sChar.length())) {
while (nLength > 0) {
// This is the sChar ANY search version
if (std::wstring::npos != sChar.find(sBuf.substr(nLength - 1, 1))) {
--nLength; }
else {
break;
}
}
sResult = sBuf.substr(0, nLength);
}
return sResult;
}
wstring PARSE$(IN wstring sMain, IN wstring sDelim, IN long nIndex) {
wstring sResult = $NULL;
LONG_PTR nLength = sDelim.length();
if (nLength == 0) { sDelim = $Comma; ++nLength; } // Use comma "," as default delimiter
sMain = RTRIM$(sMain, sDelim); sMain += sDelim;
if (sMain.length() && nLength) {
LONG_PTR prev_pos = 0, pos = 0, nCount = 0;
while( (pos = sMain.find(sDelim, pos)) != std::wstring::npos ) {
wstring substring(sMain.substr(prev_pos, pos - prev_pos));
++nCount;
if (nCount == nIndex) { sResult = substring; break; }
prev_pos = ++pos;
}
}
return sResult;
}
wstring TRIM$(IN wstring sBuf, IN wstring sChar) {
return LTRIM$(RTRIM$(sBuf, sChar), sChar);
}
int _tmain(int argc, _TCHAR* argv[])
{
HWND hWnd = GetForegroundWindow();
wstring sCaption = zGetCTLText(hWnd);
wstring sUseOption;
wstring sLastItem;
sCaption += L"<one,two,three,four,Option>";
LONG_PTR n = sCaption.length();
LONG_PTR so = INSTR(-1, sCaption, L"<");
if (so > -1) {
sUseOption = RTRIM$(UCASE$(sCaption.substr(so + 1)), L">");
wcout << sUseOption.c_str() << endl; // output to console
sCaption = sCaption.substr(0, so);
wcout << sCaption.c_str() << endl; // output to console
sLastItem = PARSE$(sUseOption, $NULL, 5);
wcout << sLastItem.c_str() << endl; // output to console
}
wcout << endl;
system("pause"); // Halts execution; shows the "Press any key to continue..." prompt
return 0;
}
Also, note the way i am using braces to come closer to the PB's IF / END IF construction.
"wcout" is the wstring way to send output to the consolde, and "endl" adds a CRLF to move to next line.
system("pause"), is handy to see what has been redirected to the console before the program close.
Patrice,
I just couldn't resist :)
If you change
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), toupper);
To
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), ::toupper);
It will also compile with MinGWTDM64
James
I use the Win7.1 SDK only. No Visual Studio.
bc9 source:
$CPPHDR
$NOMAIN
$ONEXIT "VC.BAT $FILE$ -m64 con"
$HEADER
#include <string>
#include <algorithm>
$HEADER
'==============================================================================
'CONST stdwstr=std::wstring
'==============================================================================
Function pt_INSTR(nIndex As long, sMain As wstring, sSearch As wstring) As long
Raw As long nRet = (-1)
Raw As long nLength = sMain.length()
If (nLength ANDALSO (sSearch.length())) Then
If nIndex < 0 Then
nRet = sMain.find_last_of(sSearch, nLength + nIndex + 1)
Else
nRet = sMain.find_first_of(sSearch, nIndex)
End If
End If
Function = nRet
End Function
'==============================================================================
Function zGetCTLText(hCtrl As HWND) As wstring
Raw As WCHAR buf[4096]
GetWindowText(hCtrl,buf,4096)
Function = buf
End Function
'==============================================================================
Function pt_UCASE(sBuf As wstring) As wstring
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), toupper)
Function = sBuf
End Function
'==============================================================================
Function pt_LTRIM(sBuf As wstring,sChar As wstring) As wstring
Raw As wstring sResult = sBuf
Raw As long nLength = sBuf.length()
If (nLength ANDALSO (sChar.length())) Then
Local K As long
While K < nLength
' This is the sChar ANY search version
If (std::wstring::npos <> sChar.find(sBuf.substr(K,1))) Then
++K
Else
break
End If
Wend
sResult = sBuf.substr(K,nLength)
End If
Function = sResult
End Function
'==============================================================================
Function pt_RTRIM(sBuf AS wstring, sChar As wstring) As wstring
Raw As wstring sResult = sBuf
Raw As long nLength = sBuf.length()
If (nLength ANDALSO (sChar.length())) Then
while (nLength > 0)
if (std::wstring::npos <> sChar.find(sBuf.substr(nLength - 1, 1))) Then
--nLength
Else
break
End If
Wend
sResult = sBuf.substr(0, nLength)
End If
Function = sResult
End Function
'==============================================================================
Function pt_PARSE( sMain As wstring, sDelim AS wstring, nIndex As long) As wstring
Raw As wstring sResult = L""
Raw As long nLength = sDelim.length()
If nLength = 0 Then
sDelim = L","
++nLength
End If
sMain = pt_RTRIM(sMain,sDelim)
sMain += sDelim
If (sMain.length() ANDALSO nLength) Then
Local As long prev_pos, ppos, nCount
'needed a bit of a rewrite
ppos = sMain.find(sDelim, ppos)
While ppos <> std::wstring::npos
wstring substring(sMain.substr(prev_pos, ppos - prev_pos))
++nCount
If nCount = nIndex Then
sResult = substring
break
End If
prev_pos = ++ppos
ppos = sMain.find(sDelim, ppos)
Wend
'original code
' $CCODE
' while( (ppos = sMain.find(sDelim, ppos)) != std::wstring::npos ) {
' wstring substring(sMain.substr(prev_pos, ppos - prev_pos));
' ++nCount;
' if (nCount == nIndex) { sResult = substring; break; }
' prev_pos = ++ppos;
' }
'
' $CCODE
End If
Function = sResult
End Function
'==============================================================================
Function pt_TRIM(sBuf As wstring, sChar As wstring) As wstring
Function = pt_LTRIM(pt_RTRIM(sBuf,sChar),sChar)
End Function
'==============================================================================
Function main() As int
Raw As HWND hWnd = GetForegroundWindow()
Raw As wstring sCaption = zGetCTLText(hWnd)
Raw As wstring sUseOption, sLastItem
sCaption += L"<one,two,three,four,Option>"
wcout << sCaption << endl
Raw As long n = sCaption.length()
Raw As long so = pt_INSTR(-1, sCaption, L"<")
If so > -1 Then
sUseOption = pt_RTRIM(pt_UCASE(sCaption.substr(so+1)), L">")
wcout << sUseOption.c_str() << endl ' output to console
sCaption = sCaption.substr(0, so)
wcout << sCaption.c_str() << endl ' output to console
sLastItem = pt_PARSE(sUseOption, L"", 5)
wcout << sLastItem.c_str() << endl ' output to console
End If
wcout << endl
PAUSE
Function = 0
End Function
And here is the translated c++ code
// *********************************************************************
// Created with bc9 - BASIC To C/C++ Translator (V) 9.1.2.1 (2013/02/16)
// BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
// Translated for compiling with a C++ Compiler
// On MS Windows
// *********************************************************************
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
// Additional lines may be needed
#if defined( __cplusplus )
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
typedef std::string stdstr;
using namespace std;
#endif
#include <windows.h> // Win32 Header File
#include <windowsx.h> // Win32 Header File
#include <commctrl.h> // Win32 Header File
#include <commdlg.h> // Win32 Header File
#include <mmsystem.h> // Win32 Header File
#include <shellapi.h> // Win32 Header File
#include <shlobj.h> // Win32 Header File
#include <richedit.h> // Win32 Header File
#include <wchar.h> // Win32 Header File
#include <objbase.h> // Win32 Header File
#include <ocidl.h> // Win32 Header File
#include <winuser.h> // Win32 Header File
#include <olectl.h> // Win32 Header File
#include <oaidl.h> // Win32 Header File
#include <ole2.h> // Win32 Header File
#include <oleauto.h> // Win32 Header File
#include <winsock.h> // Win32 Header File
#include <process.h> // dos
#include <conio.h> // dos
#include <direct.h> // dos
#include <io.h> // dos
#include <ctype.h> // dos/linux
#include <fcntl.h> // dos/linux
#include <math.h> // dos/linux
#include <stdio.h> // dos/linux
#include <string.h> // dos/linux
#include <stddef.h> // dos/linux
#include <stdlib.h> // dos/linux
#include <setjmp.h> // dos/linux
#include <time.h> // dos/linux
#include <stdarg.h> // dos/linux
#include <sys/types.h>
#include <sys/stat.h>
// ***************************************************
// Compiler Defines
// ***************************************************
// C++
#if defined( __cplusplus )
#define overloaded
#define C_EXPORT EXTERN_C __declspec(dllexport)
#define C_IMPORT EXTERN_C __declspec(dllimport)
#else
#define C_EXPORT __declspec(dllexport)
#define C_IMPORT __declspec(dllimport)
#endif
// Open Watcom defs
#if defined( __WATCOM_CPLUSPLUS__ ) || defined( __TINYC__ )
#define atanl atan
#define sinl sin
#define cosl cos
#define tanl tan
#define asinl asin
#define acosl acos
#define log10l log10
#define logl log
#define _fcloseall fcloseall
#endif
// Borland C++ 5.5.1 defs - bcc32.exe
#if defined( __BCPLUSPLUS__ )
// ===== Borland Libraries ==========
#include <dos.h>
#pragma comment(lib,"import32.lib")
#pragma comment(lib,"cw32.lib")
// ==================================
#endif
// Microsoft VC++
#ifndef DECLSPEC_UUID
#if (_MSC_VER >= 1100) && defined ( __cplusplus )
#define DECLSPEC_UUID(x) __declspec(uuid(x))
#else
#define DECLSPEC_UUID(x)
#endif
#endif
// *************************************************
// Tiny C support for LinkRes2Exe
#ifdef __TINYC__
int dummy __attribute__ ((section(".rsrc")));
#endif
// *************************************************
// ***************************************************
#include <string>
#include <algorithm>
// *************************************************
// Instruct Linker to Search Object/Import Libraries
// *************************************************
#if !defined( __LCC__ )
#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"advapi32.lib")
#pragma comment(lib,"winspool.lib")
#pragma comment(lib,"shell32.lib")
#pragma comment(lib,"ole32.lib")
#pragma comment(lib,"oleaut32.lib")
#pragma comment(lib,"uuid.lib")
#pragma comment(lib,"odbc32.lib")
#pragma comment(lib,"odbccp32.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"comdlg32.lib")
#pragma comment(lib,"imagehlp.lib")
#pragma comment(lib,"version.lib")
#else
#pragma lib <winspool.lib>
#pragma lib <shell32.lib>
#pragma lib <ole32.lib>
#pragma lib <oleaut32.lib>
#pragma lib <uuid.lib>
#pragma lib <odbc32.lib>
#pragma lib <odbccp32.lib>
#pragma lib <winmm.lib>
#pragma lib <imagehlp.lib>
#pragma lib <version.lib>
#endif
// *************************************************
// End of Object/Import Libraries To Search
// *************************************************
// *************************************************
// User's GLOBAL ENUM blocks
// *************************************************
// *************************************************
// System Defined Constants
// *************************************************
#define CCPTR const char*
#define cSizeOfDefaultString 2048
// *************************************************
// User Defined Constants
// *************************************************
// *************************************************
// Standard Prototypes
// *************************************************
void Pause (void);
// *************************************************
// User Defined Types And Unions
// *************************************************
// *************************************************
// User Global Variables
// *************************************************
static PCHAR *g_argv;
static int g_argc;
// *************************************************
// Standard Macros
// *************************************************
#define AndAlso &&
// *************************************************
// User Prototypes
// *************************************************
long pt_INSTR (long,wstring,wstring);
wstring zGetCTLText (HWND);
wstring pt_UCASE (wstring);
wstring pt_LTRIM (wstring,wstring);
wstring pt_RTRIM (wstring,wstring);
wstring pt_PARSE (wstring,wstring,long);
wstring pt_TRIM (wstring,wstring);
int main (void);
// *************************************************
// User Global Initialized Arrays
// *************************************************
// *************************************************
// Runtime Functions
// *************************************************
void Pause(void)
{
printf("\n%s\n","Press any key to continue . . .");
_getch();
}
// ************************************
// User Subs and Functions
// ************************************
long pt_INSTR (long nIndex,wstring sMain,wstring sSearch)
{
long nRet=(-1);
long nLength=sMain.length();
if((nLength AndAlso (sSearch.length())))
{
if(nIndex<0 )
{
nRet= sMain.find_last_of( sSearch, nLength+ nIndex+ 1);
}
else
{
nRet= sMain.find_first_of( sSearch, nIndex);
}
}
return nRet;
}
wstring zGetCTLText (HWND hCtrl)
{
WCHAR buf[4096];
GetWindowText(hCtrl,buf,4096);
return buf;
}
wstring pt_UCASE (wstring sBuf)
{
std::transform(sBuf.begin(),sBuf.end(),sBuf.begin(),::toupper);
return sBuf;
}
wstring pt_LTRIM (wstring sBuf,wstring sChar)
{
wstring sResult=sBuf;
long nLength=sBuf.length();
if((nLength AndAlso (sChar.length())))
{
long K={0};
while(K<nLength)
{
if((std::wstring::npos!=sChar.find(sBuf.substr(K,1))))
{
++K;
}
else
{
break;
}
}
sResult= sBuf.substr( K, nLength);
}
return sResult;
}
wstring pt_RTRIM (wstring sBuf,wstring sChar)
{
wstring sResult=sBuf;
long nLength=sBuf.length();
if((nLength AndAlso (sChar.length())))
{
while((nLength>0))
{
if((std::wstring::npos!=sChar.find(sBuf.substr(nLength-1,1))))
{
--nLength;
}
else
{
break;
}
}
sResult= sBuf.substr( 0, nLength);
}
return sResult;
}
wstring pt_PARSE (wstring sMain,wstring sDelim,long nIndex)
{
wstring sResult=L"";
long nLength=sDelim.length();
if(nLength==0 )
{
sDelim= L",";
++nLength;
}
sMain= pt_RTRIM( sMain, sDelim);
sMain+=sDelim;
if((sMain.length() AndAlso nLength))
{
long prev_pos={0};
long ppos={0};
long nCount={0};
ppos= sMain.find( sDelim, ppos);
while(ppos!=std::wstring::npos)
{
wstring substring(sMain.substr(prev_pos,ppos-prev_pos));
++nCount;
if(nCount==nIndex )
{
sResult= substring;
break;
}
prev_pos=++ ppos;
ppos= sMain.find( sDelim, ppos);
}
}
return sResult;
}
wstring pt_TRIM (wstring sBuf,wstring sChar)
{
return pt_LTRIM(pt_RTRIM(sBuf,sChar),sChar);
}
int main ()
{
HWND hWnd=GetForegroundWindow();
wstring sCaption=zGetCTLText(hWnd);
wstring sUseOption;
wstring sLastItem;
sCaption+=L"<one,two,three,four,Option>";
wcout<<sCaption<<endl;
long n=sCaption.length();
long so=pt_INSTR(-1,sCaption,L"<");
if(so>-1 )
{
sUseOption= pt_RTRIM( pt_UCASE( sCaption.substr( so+ 1)), L">");
wcout<<sUseOption.c_str()<<endl;
sCaption= sCaption.substr( 0, so);
wcout<<sCaption.c_str()<<endl;
sLastItem= pt_PARSE( sUseOption, L"", 5);
wcout<<sLastItem.c_str()<<endl;
}
wcout<<endl;
Pause();
return 0;
}
I have updated the first post of this thread to use LONG_PTR instead of long, to avoid potential loss of data in 64-bit.
I have also added new constant: $NULL, $Dot, $Comma
and two VAL replacements: longVAL and FloatVAL
There are so many things to think about when switching from 32 to 64-bit, including new API declarations like
GetWindowLongPtr and SetWindowLongPtr instead of GetWindowLong and GetWindowLong,
especially because long are keeping their 4-byte size even in 64-bit.
LONG_PTR has a value of 4-byte in 32-bit and 8-byte in 64-bit, thus they must be used if you want to be able to compile the same code for either 32/64-bit platforms.
???
Quote
There are so many things to think about when switching from 32 to 64-bit, including new API declarations like
GetWindowLongPtr and SetWindowLongPtr instead of GetWindowLong and GetWindowLong,
especially because long are keeping their 4-byte size even in 64-bit.
But by and large, it seems pretty easy to do. I think the GetWindowLongPtr() / SetWindowLongPtr() situation are rather singular exceptions to the rule that the Api functions themselves haven't changed much - at least from the application coder's perspective. So the issue to get 32 bit code working in 64 bit mode seems to involve nothing more than changing all the GetWindowLongs/SetWindowLongs, then changing the variable types that have anything to do with pointers, HWNDS, etc. All in all, while I was working on it, I got the impression that there were some smart people involved in dealing with this rather complex situation so as to make it as painless as possible for folks like us.
Quote
some smart people involved in dealing with this rather complex situation so as to make it as painless as possible for folks like us.
The 64 bit Windows DLLs are still called
Kernel32.dll User32.dll etc, though they are stored in a separate folder from the 32 bit system. Windows has to have a complete set of dlls for each system, with the same nomenclature for compatibility.
On the CPU side, the default operand size is still 32 bits. To get the full 64bit register width, a prefix code (REX) has to be used. The REX code is also used to access the extra 8 registers. In other respects, the opcodes are identical except for a few legacy encodings, from the Pentium's ancient 8086 lineage.
Charles
Wasn't aware of that Charles. Hadn't even given it a thought.
Recently I got a copy of Jeffrey Richter's book "Windows Via C/C++", as I always heard that was a good book on advanced Windows internals. Interestingly, in it he mentioned that Microsoft was actually running out of room in its 2.1 gigabytes segment to fit everything in its OS! I didn't realize that.
Working in plain C, I found the ellipsis (...) construct very useful when dealing with multiple params:
//gcc CharPrint.c
#include <stdio.h>
void CharPrint(char* t, ...)
{
char**pt=&t;
int i=0;
while (1)
{
if (pt[i]==0) return;
printf("%s", pt[i] );
i++;
}
}
int main()
{
char space[]=" ";
char comma[]=",";
char pling[]="!";
char cr []="\n";
CharPrint("Hello",space,"World",comma,space,"Hello",space,"Sky",pling,cr,NULL);
//Hello World, Hello Sky!
}
As long as pointers are always used, there should be no problem 64 bit compiling.
Charles
Patrice,
Are you using WSTRING/WSTRINGZ in you PowerBasic implementation or STRING/STRINGZ?
James
I am still using STRING and ASCIIZ, because WinLIFT/GDImage are still compiled with PB 9.05 to produce smaller production code.
(saving 20000 bytes) :)
And i keep using LIB instead of IMPORT for the purpose of compatibility.
...
Patrice,
I asked because I am a bit confused at the moment in which direction you are going?
I believe you said you were going to translate your PB code to both 32 and 64 bit c++ so you only had one source base?
By using c++ wstring it appears you are restricting users to those using c++ only?
James
James
I am using VS2010 Pro, and so far i can compile the same code either in 32 or 64-bit.
What i avoid is to use MFC and ATL, in order to get rid of the C++ runtime, and produce smaller and faster code size.
However my ultimate target shall be the Microsoft community (C, C++, C#), that is the largest in the programming world.
...
Patrice,
Would you be willing to share all the pb string functions you converted to c++? I started for std::string a couple years ago but never finished.
James
Here are those i have done to ease the translation between PB and C/C++.
Note: I made the choice to use only wstring (wide char).
const wchar_t *$NULL = L"";
const wchar_t *$Dot = L".";
long INSTR(IN long nIndex, IN wstring sMain, IN wstring sSearch) {
LONG_PTR nRet = -1; // Not found
LONG_PTR nLength = sMain.length();
if (nLength && (sSearch.length())) {
if (nIndex < 0) {
nRet = sMain.find_last_of(sSearch, nLength + nIndex + 1); }
else {
nRet = sMain.find_first_of(sSearch, nIndex);
}
}
return (long) nRet;
}
long LongVAL(IN wstring sNum) { // dllexport
long value = 0;
value = _wtol(sNum.c_str());
return value;
}
double FloatVAL(IN wstring sNum) { // dllexport
double value = 0;
value = _wtof(sNum.c_str());
return value;
}
wstring UCASE$(IN wstring sBuf) { // dllexport
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), ::toupper);
return sBuf;
}
wstring LCASE$(IN wstring sBuf) {
std::transform(sBuf.begin(), sBuf.end(), sBuf.begin(), ::tolower);
return sBuf;
}
wstring LTRIM$(IN wstring sBuf, IN wstring sChar) { // dllexport
wstring sResult = sBuf;
LONG_PTR nLength = sBuf.length();
if (nLength && (sChar.length())) {
//sChar = sChar.substr(0, 1);
long K = 0;
while (K < nLength) {
// if (*sBuf.substr(K, 1).c_str() == *sChar.c_str()) {
// This is the sChar ANY search version
if (std::wstring::npos != sChar.find(sBuf.substr(K, 1))) {
++K; }
else {
break;
}
}
sResult = sBuf.substr(K, nLength);
}
return sResult;
}
wstring RTRIM$(IN wstring sBuf, IN wstring sChar) { // dllexport
wstring sResult = sBuf;
LONG_PTR nLength = sBuf.length();
if (nLength && (sChar.length())) {
//sChar = sChar.substr(0, 1);
while (nLength > 0) {
// if (*sBuf.substr(nLength - 1, 1).c_str() == *sChar.c_str()) {
// This is the sChar ANY search version
if (std::wstring::npos != sChar.find(sBuf.substr(nLength - 1, 1))) {
--nLength; }
else {
break;
}
}
sResult = sBuf.substr(0, nLength);
}
return sResult;
}
wstring PARSE$(IN wstring sMain, IN wstring sDelim, IN long nIndex) {
wstring sResult = $NULL;
LONG_PTR nLength = sDelim.length();
if (nLength == 0) { sDelim = L","; ++nLength; } // Use comma "," as default delimiter
sMain = RTRIM$(sMain, sDelim); sMain += sDelim;
if (sMain.length() && nLength) {
LONG_PTR prev_pos = 0, pos = 0, nCount = 0;
while( (pos = sMain.find(sDelim, pos)) != std::wstring::npos ) {
wstring substring(sMain.substr(prev_pos, pos - prev_pos));
++nCount;
if (nCount == nIndex) { sResult = substring; break; }
prev_pos = ++pos;
}
}
return sResult;
}
wstring TRIM$(IN wstring sBuf, IN wstring sChar) { // dllexport
return LTRIM$(RTRIM$(sBuf, sChar), sChar);
}
wstring LEFT$(IN wstring sBuf, IN long nLeft) { // dllexport
wstring sResult = $NULL;
LONG_PTR nLength = max(min(sBuf.length(), nLeft), 0);
if (nLength) {
sResult = sBuf.substr(0, nLength);
}
return sResult;
}
wstring RIGHT$(IN wstring sBuf, IN long nRight) { // dllexport
wstring sResult = $NULL;
LONG_PTR nLength = sBuf.length();
if (nLength) { sResult = sBuf.substr(nLength - nRight, nRight); }
return sResult;
}
wstring MID$(IN wstring sBuf, IN long nStart, IN long nMid = 0) { // dllexport
wstring sResult = $NULL;
long nLength = (long) sBuf.length();
if (nMid == 0) { nMid = nLength - nStart + 1; }
if (nLength) { sResult = sBuf.substr(nStart - 1, nMid); }
return sResult;
}
Added:
Here is how to convert a wstring to WCHAR pointer to use with low level API calls.
(WCHAR*)MYwstring.c_str()
Note: wstring MID$(IN wstring sBuf, IN long nStart, IN long nMid = 0)
IN long nMid = 0, means this last parameter is optional with a default value of 0 (in this case 0, means take everything until the end of wstring, like in PB).
Patrice,
Thank you.
From my research I don't think the local variables are neccessary.
Doesn't this do the the same thing?
wstring MID$(IN wstring sBuf, IN long nStart, IN long nMid = 0) { // dllexport
if (nStart > sBuf.length() || nStart < 1) return "";
if (nMid == 0) { nMid = (sBuf.length() - nStart) + 1; }
return sBuf.substr(nStart - 1, nMid);
}
Patrice,
Looking into this further it looks like I had a lot more done than I realized. This is my ltrim for std::string
std::string ltrim(std::string str,std::string ctrim =" ")
{
str.erase(0, str.find_first_not_of(ctrim));
return str;
}
If you are interested I'll post the rest of the ones I converted?
James
James,
About the MID$ code you posted, it doesn't do the same than mine and PB.
MID$("1234", 5, 5) should return an empty string, not "1234".
Try it now I edited the post.
James
Quote from: Patrice Terrier on March 10, 2013, 04:54:44 PM
James,
About the MID$ code you posted, it doesn't do the same than mine and PB.
MID$("1234", 5, 5) should return an empty string, not "1234".
[/quote