FreeBASIC CWstr

Started by Juergen Kuehlwein, April 09, 2018, 11:39:00 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Juergen Kuehlwein

Yes, i know. But my point was, maybe it is possible to improve the existing workarounds for "LEFT/RIGHT" and to write a new one for the MID statement (not function - this already works) in order to get a consistent syntax (as far as possible, just like with the other, native string types), and not to have to resort to "special" handling for special cases (even if these are rare cases).

Your work on CWSTR is absolutly great and almost perfect, i don´t want to criticize it! My intention is to help to make it as perfect as possible NOW (i don´t want to wait until "one day" :-)).


JK

José Roca

I appreciate your suggestions, but they're flawed. We have to be very cautious when using BYREF AS WSTRING.


PRIVATE FUNCTION Leftx (BYREF cws AS CWSTR, BYVAL nChars AS INTEGER) byref as wstring

static s as cwstr

   s = LEFT(**cws, nChars)
   RETURN *cast(wstring ptr, *s)

END FUNCTION

DIM cws AS CWSTR = "12345"

print LEFTx(cws, 2) & LEFTx(cws, 3)   ' wrongly prints 1212
print LEFTx(cws, 2) & LEFTx(cws, 3) &  LEFTx(cws, 5)   ' wrongly prints 121212


And regarding MID as a statement, it will lose speed, a fatal flaw since the main reason of using MID as a statement it is because it is fast.

Juergen Kuehlwein

Ok José, you got me!


The intermediate storage (which i would prefer to avoid anyway) bites me. What about this:

PRIVATE FUNCTION Leftx (BYref cws AS cwstr, BYVAL nChars AS INTEGER) as string
  function = LEFT(*cast(wSTRING PTR, cws.m_pBuffer), nChars)
END FUNCTION

according to my tests it works, can you make it fail ?


Another thing i don´t understand, is why the compiler won´t let me do this:

Function Leftx ( ByRef str As Const WString, ByVal n As Integer ) As WString


the code is taken from the help file ("Left"), but it doesn´t compile ("Expected pointer in: <this line>")


All this type casting, even with pointers, is driving me crazy. You know i have some assembler background and there a pointer is a pointer and (seemingly) non-matching types aren´t just rejected with error messages, i don´t understand. In FreeBASIC it is sometimes really frustrating to find a way to make the compiler happy.


JK

José Roca

> according to my tests it works, can you make it fail ?

Of course. Try using it with Russian, for example, instead of "12345".


PRIVATE FUNCTION Leftx (BYref cws AS cwstr, BYVAL nChars AS INTEGER) as string
  function = LEFT(*cast(wSTRING PTR, cws.m_pBuffer), nChars)
END FUNCTION

DIM cws AS CWSTR = "Дмитрий Дмитриевич Шостакович"
PRINT LEFTx(cws, 3)


Will print ???", which is the expected result since you are returning it as an ansi string.

Believe me. I did lose countless hours trying to find an acceptable solution, but since it is a bug of the compiler, the solution will be to fix the bug.

Anyway, with the current overloads, it works except with SELECT CASE LEFT/RIGHT. I didn't even know because I never have used LEFT and RIGHT with SELECT CASE. Indeed there are easy workarounds: assign it to a variable first, use MID or use **.

I have managed to get an almost total integration with FreeBasic instrinsics. It even works with files, e.g.:


DIM cws AS CWSTR = "Дмитрий Дмитриевич Шостакович"

DIM f AS LONG = FREEFILE
OPEN "test.txt" FOR OUTPUT ENCODING "utf16" AS #f
PRINT #f, cws
CLOSE #f


José Roca

#19
Quote
Another thing i don´t understand, is why the compiler won´t let me do this:

Function Leftx ( ByRef str As Const WString, ByVal n As Integer ) As WString


A WSTRING in FB is not like a WSTRING in PB. The PB equivalent is WSTRINGZ and, of course, you can't return a WSTRINGZ or an ASCIIZ as the result of a function. The compiler is expecting AS WSTRING PTR.

Quote
the code is taken from the help file ("Left"), but it doesn´t compile ("Expected pointer in: <this line>")

It is not an example, but a prototype to document the function. It means that the native Left function will return a WSTRING, not thatyyou can use AS WSTRING as the result of your own function. Don't confuse the prototypes used to document the FB keywords with code.



José Roca

BTW I don't understand why you want to make your future visual designer to generate ansi or unicode. Only unicode is needed. There is not a single advantage of making an ansi GUI. Even the latest PBWIN compiler uses unicode only.

José Roca

#21
Quote
All this type casting, even with pointers, is driving me crazy. You know i have some assembler background and there a pointer is a pointer and (seemingly) non-matching types aren´t just rejected with error messages, i don´t understand. In FreeBASIC it is sometimes really frustrating to find a way to make the compiler happy.

FB has been written by C programmers and these guys are used to use casting in almost each line of code. This could be changed by using ANY PTR in the declares. FB uses BASIC syntax, but the declares have been prototyped to use them like with C.


Juergen Kuehlwein

José,

Quote
Believe me. I did lose countless hours trying to find an acceptable solution

... accepted! Nevertheless this discussion wasn´t useless (at least for me). I definitely learned something and you showed a workaround for LEFT/RIGHT - MID, which can have the same syntax for both!



Quote
I don't understand why you want to make your future visual designer to generate ansi or unicode


Well, there weren´t dynamic Unicode strings in FreeBASIC before you came. Therefore i think not many at FreeBASIC are familiar with it. If the Visual Designer produced only Unicode, many could be deterred. So the idea is to pick them up where they are (ANSI) and show and easy way to switch to Unicode. As far as possible i would like everybody to be able to have it his/her way.


Thanks a lot - i will ask questions again as they arise...


JK

José Roca

#23
In fact, because it has casts to return either the content of the string or a pointer ro the beginning of the string data, depending on the target type, there is not need for STRPTR, which won't work anyway.


' // Populate the ListView with some data
DIM cwsTxt AS CWSTR
DIM lvi AS LVITEM
lvi.mask = LVIF_TEXT
FOR i AS LONG = 0 to 29
   lvi.iItem = i
   lvi.iSubItem = 0
   cwsTxt = "Column 0 Row " & i
   lvi.pszText = cwsTxt
   ListView_InsertItem(hListView, @lvi)
   FOR x AS LONG = 1 TO 4
      cwsTxt = "Column " & x & " Row " & i
      ListView_SetItemText(hListView, i, x, cwsTxt)
   NEXT
NEXT


José Roca

#24
Another workaround for SELECT CASE LEFT


SELECT CASE LEFT(cws.wstr, 2)


It also works for MID


MID(cws.wstr, 3, 2) = "AB"


It does the same that **, but those not familiar with pointers may prefer it:


' ========================================================================================
' Returns the string data (same as **).
' ========================================================================================
PRIVATE FUNCTION CWstr.wstr () BYREF AS WSTRING
   CWSTR_DP("CWSTR wstr - buffer: " & .WSTR(m_pBuffer))
   RETURN *cast(WSTRING PTR, m_pBuffer)
END FUNCTION
' ========================================================================================


José Roca

And if someone can't live without STRPTR, instead of


lvc.pszText = cwsText


he can use


lvc.pszText = cwsText.sptr


Juergen Kuehlwein

José,


i can live without "STRPTR" perfectly well, especially since i know (and i understand why) i can pass the string instead of its pointer. "MID" can be a replacement for the buggy "LEFT/RIGHT". So i can have the same syntax for both, which is my objective.

I want to present a working solution first - then i can come up with explanations, that this or that, which may look strange, isn´t due to my bad code or some shortcommings in CWStr but a known compiler error and that you must accept certain minor restrictions when using it. To my experience most of times people don´t want to hear (or even know) about things that don´t work - they want to hear about things, that work (and maybe then about how and why it works).


Thanks again,


JK

Juergen Kuehlwein

Maybe a stupid question, but how to enter russian letters in CSED? I must check "Enable unicode (UTF-8 encoding)" and then? E.g. Alt + 0411 (Numpad) should result in a cyrillic capital b. I can paste cyrillic characters, but i don´t know how to type them.


JK

José Roca

I never have tried. You have to activate cyrillic support.
See: https://www.wikihow.com/Type-Russian-Characters

Juergen Kuehlwein

José,


while FreeBASIC accepts ANSI, UTF-8 and UTF-16 encoded code files as sources, PB´s compiler accepts only ANSI files, so how to embed unicode literals in code? You may append "$$", but that doesn´t allow for giving unicode insde the quotation marks. I could do something like this:


$$russian = chr$$(&H416,&H416)        -> Scintilla + PB´s IDE
w$$ = Utf8ToChr$("ФЫЙЦ")              -> Scintilla (PB´s IDE cannot display UTF-8 properly)


did i miss something ?


JK