yoy.be "Why-o-Why"

Do n.GetFirstChild=nil instead of n.Count=0

2021-03-21 17:25  nodecount0  coding delphi  [permalink]

I wish I knew this one sooner! If you've worked with TTreeView before, and know about TTreeNode's HasChildren value, you need to check with OnExpanding, if you need to load the children or not. So I would typically have something like this:

if Node.HasChildren and (Node.Count=0) then //load children nodes

Only now after all these years I happen to come past this in the Vcl.ComCtrls.pas unit:

function TTreeNode.GetCount: Integer;
var
Node: TTreeNode;
begin
Result := 0;
Node := GetFirstChild;
while Node <> nil do
begin
Inc(Result);
Node := Node.GetNextChild(Node);
end;
end;

So I've been throwing away performance all this time! Because my 'are the children loaded yet' check was taking more time if they were and there were a lot of them, expanding nodes was slower. And I never noticed!

So it's a good thing I know this, and now I can just write:

if Node.HasChildren and (Node.GetFirstChild=nil) then //load children

twitter reddit linkedin facebook

205B random strings and no 'Delphi'

2021-02-28 18:48  randomdelphi  coding computers delphi werk  [permalink]

→ Delphi-PRAXiS: Can Delphi randomize string 'Delphi'?

Ah, that takes me back. A while ago at work I got someone baffled by this statement: It is said that a thousand monkeys banging away on keyboards could at some moment in infinite time produce the complete work of Shakespeare (and that the combined internet forums are a living counter-proof). Now if you search online you can find an XML download of the combined works of Shakespeare, so it's not hard to find the relative occurance of each letter of the alphabet. One can guess this will have rougly the same values per letter as the total of the English language. So, then, if you take 'random' by its definition, and the monkey's produce text at 1/26 probability for each letter in the alphabet, therefore they'll never reach a point in time where they (re)produce the works Shakespeare.

Now, I'm not a real philosopher, or a statistician, so my thesis could be complete fiction and based on nothing, but sometimes you really got to take a lesson from practice. In theory, in infinite time, it's ofcourse possible that something really really inherently possible could emerge out of a random system, but there are characteristigs to anything random, and there are exponential things at play that soon but experimantal set-ups like with the link above, that they probably would produce the expected outcome in a time-span that exceeds the number of years we've got left before the sun sheds its outer layers and devours the earth, complete with a set of silicon-based machines churning away at putting a series of random characters in sequence and comparing them of some neat stories of a long gone English playwright.

twitter reddit linkedin facebook

DIY Google Authenticator

2021-02-25 20:12  diytotp  coding delphi internet freeware  [permalink]

Recently, I've got a few things asking to enable two-factor-authentication, and I started using the Google Authenticator app.

I kind of like it. It's a simple enough app, there's a shared secret involved, but it gets pretty close to being airgapped and perfectly forward secure and all of those things. So I got thinking... What would it take to start using it for myself, in those little software things I create now and then...

Is there black magic or stick whittling involved? Nah, a little searching around, and it all appears to be cleanly described in RFC's 6287 and 4226... There has to be a warning here about not rolling your own crypto, but the world of hashing and encrypting really is interesting! I did SHA1 and HMAC before, and Unix' time apparently is UTC... So all you need* is the correct format of URL to put into a QR-code to load up a new key in the app. Then you can use this code to generate the 'current' pass-code for the secret:

github.com/stijnsanders/tools/.../crypto/totp.pas

*: and apparently base32-encoding, HashUtils was missing that...

twitter reddit linkedin facebook

Lobsters on Delphi: the good and the bad

2021-02-18 00:20  lobsters  coding delphi dotnet  [permalink]

→ Lobsters: 26 Years... of Delphi

Aaw, look at that, the good and the bad on a single page.

twitter reddit linkedin facebook

Good to know: don't do except on e:Exception do ... raise e;

2020-12-28 13:29  dontraisee  delphi werk  [permalink]

Good to know. At work, I inherited a smaller project. It started firing access violation errors reading from 00000000 (that tells you there's a nil pointer involved somewhere) at some address that didn't put me somewhere in the source code when I did Search > Find address in the IDE...

I was lucky I got the program running in a debugger when this happens, and the root cause was something completely different. (An SQL unique index constraint violation if you're really interested.) I got that fixed soon enough, but that didn't explain where the access violation comes from.

I followed the exception with the debugger, and before the exception was handled by anything that outputs like a logger or an error display, sure enough an access violation happend, but the debugger didn't show me anywhere else in the source code than it was already debugging, strange.

It took me a long hard look at the code before I spotted it, but with some luck you'll be able to spot what's wrong faster. The original author had the strange habit of writing exception handlers like this:

try
//important stuff here
except
on e:Exception do
begin
//stuff to do in case of an exception here, (e.g. transaction rollback)
raise e;
end;
end;

And they were all over the place. Nothing bad about that per sé, with raising the exception again, you can centralise the actual exception handling on the 'highest level' where all the calls are made. But while you're able to raise a specific exception if you create a new one*, apparently there's a difference between raise e; and raise; at least in this Delphi version I was on. Delphi handles the destruction of exception objects for you, and apparently that throws something off and causes the nil access violation somewhere deep inside...

*: Fun fact: Did you know that the Delphi runtime system creates an EOutOfMemory exception instance at the start of your programs, just to have it ready when it actually runs out of memory anytime later? Forgot where I read about that though...

twitter reddit linkedin facebook

QuickReports: R.I.P. Lut

2020-12-18 16:26  invoicetemplates  coding delphi werk freeware  [permalink]

→ https://stackoverflow.com/questions/65348138/quickreport-on-delphi-sydney-10-4-1

Oh my, I didn't know. I guess we'll see this more and more with one-person open-source projects, that people stop with the project for all kinds of reasons.

But about reports, I've made this really elegant thing at work to script the design of a report with just a few basic commands (line, text, image, matrix, block, repeat...) that allows you to write what the report should look like, and make lots of small alterations later. If you really need your reports just right, I've always found a graphical designer to introduce minor artefacts that you sometimes need to work around...

I know there are tons of similar things out there, like TeX and PostScript, and even HTML or MetaFiles, but it was grown out of neccessity and suffered "dogfooding" from the very start, which shows in its design and execution. And thanks to SynPDF, (or "Print to PDF" for that matter) you can just exports PDF's with it as well. So I really should take some time and re-do it on my own time and open source it... If I can make it even better and cleaner, I might introduce the open-source version as a replacement at work! (... Oh-oh!) (... or was it this one?)

twitter reddit linkedin facebook

Why no C++ webdev...

2020-06-05 17:23  cppwebdev  coding delphi internet  [permalink]

→ Quora: Why is C++ not used in web development?

For what it's worth, in creating xxm it feels like I'm trying to create this exact thing except for with the Object Pascal language. Yes, you can do HTTP all by yourself, you can do an ISAPI extension DLL or a Apache httpd module, but you'll still get a strange hybrid between a server service and a web application that has nothing like a platform you can depend on to do the heavy lifting. And, if I'm permitted to speak frankly, in C++ this would be ugly! And probably would need a lot of code to make even the basic things happen. Too bad (Object) Pascal has been called verbose, if you know what you're doing you can write the logic you need in concise readable syntax.

Still what I'm finding in trying to get people to take a look at xxm, they either are unable to disregard the visual RAD form-designer style programming like I do, and don't get that xxm in it's current for is much more like early-days PHP but with the Delphi compiler instead of the script interpreter server-side; or they are fixed in thinking 'the web + Delphi' is all about a data-layer, doomed to only serve plain CRUD requests to and from a front-end layer, and never talk to the user's browser directly. Please! A big strong no on both accounts. Let me explain.

I've always seen — pretty much since FrontPage and DreamWeaver — that if you have a visual designer to manage what to go on a HTML page, you get really ugly code. It'll look the way you want, but a lot of decisions have been made for you. Some with negative consequences for you down the road. And the underlying code is strange and ugly, unneccessarily complex for your website-visitors' browser to work with. I guess modern front-end web-devs must have known this also as I've seen a regression towards working on big chunks of raw coding the last decade. Yes, font-ends are hacking away in CSS and HTML, and not with their bare hands, all kinds of CSS pro-processors and template engines do the heavy lifting behind. So if you know what you're doing, you can have this as well, in a Delphi project. I don't need a form designer, I make the page-builder first with dummy data, and run it in the browser. Don't forget, hitting F5 in the browser to an xxm website running over a development-handler, fires up the Delphi compiler there and then. Edit→Save→Refresh→Repeat

Then there's the other thing. If you start a conversation about webservers and Delphi, bam there's DataSnap. Strange. Is it because I'm strongly dys-convinced about ORM's? (Reminder to self: still have to write that grand essay about what's bad about ORM's.) Yeah sure, if you have things that use RTTI to serialize your data-objects in some way, you can easily use one of the available options to serve it over some web-server and bam you can call it REST and get away with it. But this is a completely different thing than having a full blown web-application serve from something you created! Complete with images and stylesheets. And yes you can have both🤯 from the same web-server-service🤯. I've had people walk away, unable to believe me. It still feels like it's a case of opening your mind to be able to see it.

Anyway, sorry about the rant. I'm getting tired of trying to find the people that combine real web dev with Delphi for the server side. Yes there are a lot of new things that compile (Object) Pascal to JavaScript, but that's another story. That's nice for the front-end. But if you dig deeper, or want to reach the people that you can't offload your gargantuan client-side workhorse to, please think about xxm. Give it a try, see if you can make it work. If you want an example of what I'm talking about, take a look at feeder or tx.

twitter reddit linkedin facebook

Whaddayaknow, it checks out!

2020-05-27 10:30  primescheck  coding delphi  [permalink]

→ Primes...

J: Doc/Articles/Play104: The 10,000,000,000th Prime Number

http://yoy.be/home/primes/?a=2&x=10000000000&t=1&n=1 p(455052511)=10000000019 is actually the first prime past 10^10, but that does mean my primes thingy found the 455052511 primes lower than that.

http://yoy.be/home/primes/?a=1&x=10000000000&t=1&n=1 p(10000000000)=252097800629

twitter reddit linkedin facebook

Microsoft Teams was down?

2020-03-16 20:29  nottx  actueel coding computers dagboek delphi werk freeware  [permalink]

→ Microsoft Teams goes down just as Europe logs on to work remotely — Verge

Tx wasn't down, especially the instance you host yourself.

twitter reddit linkedin facebook

About x in ['0'..'9'] and CharInSet

2019-11-05 22:42  anticharinset  coding dagboek delphi  [permalink]

I'm still in the (slow) process of letting go of Delphi 7 and embracing the modern version(s) of Delphi, which to be honest was only possible since there's a community edition (that includes the stand-alone compiler(s)). I was in doubt if I would move over to the WideChar based default string, but since Windows internally switched long ago — and you get emoji-support for free — I thought I should switch also and haven't even tried to override the new default and switch string to be AnsiString just to keep things the old way. It works remarkably well. Any code that assumes the length of the string is also the number of bytes to move around needs to change, but that's a good opportunity to change them over to operations that use encoding support. With PChar and char that also changes mapping (to PWideChar and WideChar respectively) any coding use those just keeps working. Except in code like x in ['0'..'9'] which I apparently use a lot. It works except when compiling it throws this warning:

Warning: W1050 WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in 'SysUtils' unit.

At first I was baffled. Why is it reduced to a byte char? I know set expressions trigger all kinds of compiler optimizations (that's why I like to use them so much), but has someone been too lazy to make them happen with 16-bit values as well? I guess we're talking assembler jump-lists here, so it probably matters if you can limit them to 256 positions, and 65536 positions would add too much of dead chunks of data into your compiled code... But still. x is WideChar, any '0'-style literals should default to WideChar, shouldn't they? So I regret there was no preference to support code re-use here, and CharInSet which appears to be just a wrapper around the in syntax, strange.

I don't like warnings and hints. I typically avoid them at all cost, treating them as compile errors. It helps to keep your code clean, and avoids trouble down the line. (But if you're really into avoiding trouble down the line, you should do decent static code analysis...) I'm kind of strict on myself that way. So I need to know what's the best way to avoid this warning. In someone else's code I saw x in [WideChar('A')..WideChar('Z')] but that doesn't appear to suppress this warning. So I settled on AnsiChar(x) in ['0'..'9','A'..'F'] which probably calls a Unicode conversion routine, but I don't care enough. Old Delphi understands it, new Delphi no longer throws an error, and as far as I know the compiler optimizations still kick in and I haven't seen any performance loss over code like this. So I can sleep again.

Unless someone throws me a much better alternative and I won't sleep for a week because it feels like I should have known that all along...

twitter reddit linkedin facebook

Databases inside Delphi Ecosystem

2019-10-08 22:40  lgdbdelphi  coding delphi  [permalink]

→ landgraf.dev: Databases inside Delphi Ecosystem: Webinar

Ugh, ORM? No thank you. I still need to write the full and extensive treatise about why exactly I prefer not to use ORM's, but every time I see something like "Databases in Delphi", and see the content rapidly veers toward heavy pre-moulded data-layers that bind you to things like ORM and REST API's, I regret so many people fall into this trap. Beginners think they're keeping things easy and scalable, but all hit the same wall later up when performance and complexity is letting them down hard, in part because of these basic choices made up front. I think it's very important to educate newcomers about the alternatives. There are downsides to ORM and heavy data-layers that you should know about.

Which I'm planning to address in a specific page "Why I dislike ORM's". One day. When I'm ready. For now I'll just say I'm glad I've stayed clear of them. I've looked beyond what's typically put forward as the only alternative, and went behind any platform, to talk to SQLite, PostgreSQL and MongoDB directly, unhindered. You get something working relatively quickly. It allows me to tap their full potential and have them scale right along with the front-end as it needs to grow to handle a larger volume of requests. I'm not saying it's perfect. This kind of architecture also has its downsides, but it has one big dependency less into the mix.

twitter reddit linkedin facebook

Feeder: support WordPress API "wp/v2/posts"

2019-09-14 23:40  wpv2posts  coding delphi internet freeware  [permalink]

Is it normal that a WordPress website serves it full "https://api.w.org/" REST API from the home page (e.g. https://foreignpolicy.com/)?

I just happed to notice <link rel="https://api.w.org/" href="..."> while I was looking for an RSS url. So I had to have a closer look. It looks like it's open for anyone to POST new posts to /wp/v2/posts?!

Anyway, I've created support for it in feeder/eater...

twitter reddit linkedin facebook

PDF-web: tried forms but nought

2019-08-09 18:40  pdfweb  coding delphi internet  [permalink]

A while ago I thought, since modern browsers show you PDF documents conveniently in the same window, could you make links work and have a dynamic webside that serves PDF pages?

But yes ofcourse you can. Then I also recalled it's possible for a PDF document to have form fields you can fill in. I tried, but the PDF viewers in modern browsers don't appear to support those. (Yet? Give me a ring if they ever do and I'll see what I can do.)

Update: Oh, what's this? Looks like they're working on it...

twitter reddit linkedin facebook

A PDF website

2019-07-14 00:54  pdfweb  coding delphi internet freeware  [permalink]

I had an idea. PDF nowadays open right in the same browser window. We can thank the steady progress of the JavaScript ecosystem to make this possible. And also more secure, if I understood correctly.

Also, in a PDF you can mark text or a rectangle as a hyper-link. So it should be possible to create a dynamic website that uses PDF instead of HTML, right? One way of looking at it is that PostScript in PDF is a way to layout things on your page just like HTML is.

Anyway, I had to see how much of work it would take to make a proof-of-concept. So here it is, it's not much on the dynamic side, but it's a site that opens to a PDF, and links to another page of the same site.

https://github.com/stijnsanders/pdfweb

twitter reddit linkedin facebook

I'll be there: Delphi Day 2019 - Brussels 9 May

2019-04-23 11:39  delphiday2019  actueel delphi werk  [permalink]

May 9: Delphi Day 2019

I'll be there.

twitter reddit linkedin facebook

Local variables don't cost nothing!

2019-03-08 22:45  nocostvar  coding computers delphi werk  [permalink]

O my god. I can't believe I have to keep explaining this. To a years-long colleague with some more years on the counter than me, the other day. He repeated a function call with the same arguments a few times in a few adjacent lines of code, with a guarantee in place that this will result the same value every time.

I asked him why. It couldn't be to have less typing: the extra var a:integer; would replace far much more code it took for the repeated function calls. It couldn't be performance: even if the function would just be getting a value from a memory location, the call and return, building a stack frame and tearing it down it again, would end up in a multiple of the instructions the processor needs to work through.

I don't know who launched the idea the compiler should be smart enough to pick things like this out — what I read about Rust and other modern languages, I know research is actively looking at things like that — but as we currently have it, our good old trusted compiler doesn't. What is does do, and typically really well if we work a little with it, is mapping local variables onto the available registers of the CPU. In the best case no memory whatsoever is allocated for local variables.

Even if in theory some local variables get a temporary address on the stack, modern CPU's have multiple levels of cache so that the values don't even reach your DRAM silicon before you're function call completes. We're supposed to keep all functions and methods as short as possible, but even if we don't, the compiler knows if a local variable is only used for a short section of the code. So in some cases it's even better to have an extra local variable instead of re-using a local variable somewhere up front and then later near the end of a larger block, and still not pay with any performance of memory consumption...

So when in doubt, take an extra local var. It's what they're there for. It helps the compiler do better analysis. It helps you, now and later. All I need to do now is name them a little better. I know I have the nasty habit of things like var a,b,c,d,e,f,g:integer; but I think I'm improving... Slowly...

twitter reddit linkedin facebook

jsonDoc v1.2

2019-01-18 08:53  jsondoc12  coding delphi freeware  [permalink]

I don't really know where my open-source/freeware projects get used by other people (and I don't really care all that much, really), but ofcouse where I use my private libraries in the projects of my day job, I've got a first-row seat to see how they perform. No, even better, I'm the stagehand. I know it's important to keep the two separated though. At work I can only use and call libraries, never work on them. I can make changes, but I would have to do so like anybody else: clone a local repository, store the changes there, and when they're ready have the good manners of sending out a pull request. If 'at-home’-‘hobbyist-programmer’-me decides to merge it, it makes my employer a co-creator of the project, creating a new legal situation that my employer would need to know about.

What I can also do, ofcourse, is let private-me know that ‘at-work’-me would really like this or that extra feature or interface, and then when I can put some evening time into programming, I can see if I get round to it. Github issues are nice for that. Or Post-It's on my car key...

But recently I've got a real decent suggestion from a collegue. It didn't come in over a pull request, but it made sense, so why not put it in at the base:

https://github.com/stijnsanders/jsonDoc/commit/fb01e0865fa888c7441234726dc4a90b0c802582 

The IJSONDocument interface has Parse to load data from a string holding JSON data, and a function ToString to convert the contents back to a string. For jsonDoc (and bsonDoc before that) I want concise syntax, so I though I'd make Parse a function that returns Self so you can chain calls. But my collegue wondered why IJSONDocument doesn't have a property AsString:WideString;. In theory it would have read ToString write Parse, except Parse needs to be a procedure, not a function. So I had a close look and changed it around. Another option would be to add an extra procedure SetString, but that would mean the virtual method pointer table for the IJSONDocument interface would have an extra item, to a method with exactly the same behaviour, which makes little sense.

So I changed it around. If you really like/need chaining, there's still the function JSON overload that takes a Variant. If you pass it a string, it'll call plain function JSON to get a new instance, and call Parse for you on the string.

twitter reddit linkedin facebook

NoSQL agent with SQL back-end(s)

2018-12-29 15:41  nosqlidea  coding delphi freeware  [permalink]

It happened again. I get this great idea that slowly develops, and gives the feeling I'm on to something, but nowhere near any time in the forseeable future to put in to it and get a proof-of-concept of a first project that makes it work. So, for what it's worth, I write it down here fast in the hope sharing it with you may give more chance to this idea getting useful.

I've read that some NoSQL solutions are actually about eventual consistency, meaning in the best case of a query for data that was just inserted or updated could already return this new data if the server(farm) ad already fully processed it. Worst case is that it just for a few milliseconds totally disappears, but that's another story altogether.

I haven't done anything serious with NoSQL yet, and really a lot on good old SQL, and recently with SQLite which I've really grown to love in a short period of time. But still there's something there that's really suited for the new style of programming that is going on with all the new web projects and this 'Internet of Things' everything is on about... To find out, I've been trying interfacing with a number of them from Delphi in the most direct way I could possibly find and make work with reasonable effort. I like how TMongoWire worked out, to talk with PostgreSQL all you need is in the libPQ.dll, but a number of others just stick with a plain HTTP API where you PUT and GET things on their own URL. There's a beauty to that, really. The structure of your documents is nicely contained in JSON, and HTTP is such a stable platform you're sure to be able to access it from almost any platform.

So that's where the idea came from: what if I made my own service where you can just put or get JSON documents? But on the back-end jsonDoc would do the heavy lifting and the storage itself could be in a decent SQL service. And/or it could be in something intermediate like memcached. And/or the saving to storage could be asynchronous somewhere close after the actual PUT call (hence the eventual consistency).

For example, you fill a collection of items with things with a number of fields, for example one is "Price", but later you need the items above or below a certain price, you would do SQL "select * from Items where Price<@p". So in this service I'm imagining, there would be meta-description on the collection that you've provided a SQL database somewhere, but the service is responsible for having done the "create table Items (ID some primary key, DATA json, Price decimal(8,2))" and filling it with the data.

And this would be the beauty of it: if you need an extra column later, you just say so, and the connector would be responsible for the "alter table Items add ..." and filling that column with the data from the stored items. Perhaps even slowly, asynchronously together with the other work. Or even another connector alltogether, let's say PostgreSQL and MySQL side by side, perhaps even as a fail-over for eachother.

But I'm dreaming. It would be a load of work just to get something to work, and even more work to get enough connectors to work good enough to even demonstrate how it would work. And then there's the performance trails... And the evangelising to see wether it solves other people's problems anyway... It would be a really great opportinity to finally cut my teeth on this IOCP thing.

twitter reddit linkedin facebook

Update to SQLite 3.26 as soon as possible

2018-12-24 14:52  sqlite326  coding delphi freeware  [permalink]

It's very rare something turns up in the SQLite package, but when it does is best to give it some attention. So, very esteemed users of TSQLite — and anyone else, really — I strongly suggest you upgrade to version 3.26 of sqlite3.dll since recently some dangerous vulnerabilities have been uncovered. I checked, and nothing extensive changed to the API so chances are nothing should break if you only update sqlite3.dll and not SQLite.pas and SQLiteData.pas. Also, happy Christmas!

twitter reddit linkedin facebook

TOML? YAML? ini-files? JSON? Loosen up!

2018-12-10 11:26  jsonloose  coding delphi freeware  [permalink]

TOML? YAML? plain old INI-files? or shiny and new — but strict — JSON? Nàh. I've made myself something better. In jsonDoc.pas I've recently added an optional compiler define JSONDOC_JSON_LOOSE that makes the JSON parser a whole lot genter to work with. Some things are no longer required: the root document doesn't need to start and end with braces ("{}"), the quotes around the key names are no longer required (unless they contain special chars), the comma's between key-value pairs are no longer required, it accepts equal ("=") between keys and values instead of colon (":") and can even do entirely without.

And while I was at it there's also JSONDOC_JSON_PASCAL_STRINGS that allows you to write string literals the Delphi way: between single quotes, and double single quotes where you want a single quote in the string value. This way — really handy in Windows environments — it doesn't require you to escape backslashes.

The only downside maybe is that you need to add the defines to the compiler parameters, but for plain old configuration something like this:

x=5
y=10
output='C:\test\output\'

looks a lot nicer and like what we're used to, and gets parsed just the same as if it was written like this:

{
"x":5,
"y":10,
"output":"C:\\test\\output\\"
}

twitter reddit linkedin facebook

xxm 2.0? About the big plan

2018-11-28 22:50  xxm2plan  coding delphi weblog freeware  [permalink]

Should I begin on xxm v2.0? Delphi having a Community Edition is really really great news, not only for all of the Delphi community, but also for me as a hobbyist programmer with a number of freeware opensource projects out there. Except I was one of those that stuck with Delphi 7 up till now, so next to myself being fully convinced to finally take the step, I also need to have a look project-per-project how to lift them into these modern times and upgrade them to full Delphi 10 projects.

One of my darlings is xxm. You can compile xxm with modern Delphi just fine. I switched string to AnsiString or WideString explicitly nearly everywhere, so you shouldn't get as much as a hint. (Except mayby somwhere where I still have case x in ['A'..'Z'] of or something like that where x is a char and thus is a WideChar, and the compiler doesn't like that). But I'm worried about how I chose to set up the project. I thought I was best to just inherit from IUnknown and define a decent interface and build everything around that. But several xxm projects later, some that are even running some decent production load at work, I learned some things, most importantly these two:

It looks like xxm doesn't need to work with object instances. Requests are coming in, something needs to build a response, but having to have your objects set up first before you can get crackin' now appears as something I should have tried to avoid. Specifics and identities are handled by the underlying communication framework anyway, so you can get by with just a reference, and request more with that reference only just when you need it.

The other is that with the dynamics of IUnknown pointers, you're still dragging this COM thing with you. Yes it may be wafer-thin really and proven tech, but it's still something removing you from what really counts: pointers to where the code is to run. If you're really (really!) pushing to get the last drop of jouce from the orange performance-wise, it may be just that last thing that's in the way. Even when you avoid any locking in reference counting.

So this is the big plan for the moment: if I get to put some decent time into the project, over the next year(s), I'm considering starting a blank project xxm 2.0, start with a plain C style interface with just procedure and function pointers — a really really ancient looking interface — that has everything that IXxmContext and related interfaces have now. Then re-start with xxlProto and xxmHttp to make that work,  then a new xxmCGI, xxmSCGI, xxmISAPI, xxmAhttpd (and perhaps now really a xxmFastCGI, but no xxm IInternetProtocol any more, sorry) and then have a first new push to see how it performs, with IOCP and http pipelining, and who knows HTTP/2 or HTTP/3 that'll have materialized by then.

After that I was thinking I need a new implementation of IXxmContext that just patches through to the new xxm 2.0 calls, so you can very easily and without a worry add it to an existing xxm v1 project and run it with the xxm v2 handlers, enjoy the performance benifits and slowly change things over to xxm v2 where you need to — or not at all, really.

I hope it's a good plan, but for now it's all a dream. I haven't been able to put much time into my hobby projects lately, but it fluctuates and if it picks up some I'll see how far I'll get. Along the way I still hope to find more people that are searching for a good way to combine good old web-scripting with the power and speed of the Delphi compiler, and can count on xxm to offer good debugging, easy live-updating and a stable and secure platform for their web projects.

twitter reddit linkedin facebook

TMongoWire on jsonDoc v1.1.8

2018-11-01 17:24  mwjd118  coding delphi freeware  [permalink]

→ TMongoWire commit 78c7c62: jsonDoc v1.1.8

I may have decoupled the bit that works with structured data (using Variants), and converts to/from JSON, into a separate project jsonDoc, and have converted TMongoWire to run on jsonDoc, I also should take the time to update TMongoWide when jsonDoc gets improvements. The fact is I'm doing much more with JSON than on MongoDB recently, so I risk letting this slip out of sight.

What I also should do is set the TMongoWire repository up so it uses the jsonDoc repository as a git module, but for now it's just about one single file so I'll see when I get to it (...).

twitter reddit linkedin facebook

Done! Feeder now on PostgreSQL

2018-08-31 20:25  feederpq  coding delphi  [permalink]

Tadaa! Thanks to DataLank, I was able to switch feeder from SQLite to PostgreSQL in roughly one evening. You just need to change ifnull to coalesce, (and SQLiteData.pas for LibPQData.pas ofcourse) and storing Delphi's TDateTime values now map to genuine timestamp values, so it's a little different to do arithmetic with...

But I was getting some 'database locked' errors, so I guess it was the best thing to do, since SQLite works really well but isn't quite designed for use by a website, let alone multiple processes. Sorting by timestamps appears to take a little more processing power than I was expecting, so I may try to change back to storing them as double (since that's also the value TDateTime uses internally), or I may just be missing an index that could speed up the query. It takes some investigating to find out, but that's for another day...

Update 2018-10-12: With some regret, I need to inform you that I have switched back to SQLite, perhaps for the time being. Though operation was acceptable, I noticed quite some performance was lost on queries that depend on the values in the fields of type timestamp without timezone. I've had a look if I could fix this by adding indexes, but wasn't successful. I was also thinking about changing the date-time fields to float, as that's what's actually used in the Delphi code that handles the values, and would probably get better performance in comparing and sorting in PostgreSQL, but the time it would take to switch that around would exceed the time it takes to switch back to SQLite. And switching back to SQLite offers a situation that has shown to perform well in all cases. With this switch I can find some time (somewhere?) to read up on PostgreSQL and timestamp fields, and what I'm missing that was causing some queries to take abnormally long. The query that averages times between posts, prior to checking feeds for new posts would regularly take over 100 seconds, a query that SQLite would only take seconds over.

Update 2019-08-19: Aaaand... we're back on PostgreSQL. This time I decided to use float for all date fields. Not only because Delphi uses this internally (and so there's less conversion to do), but also because PostgreSQL knows what to do with them, for example is able to sort by them.

Update 2020-01-30: I've also added an optional chart that gets generated by the feed reader schedule, that gives a view of the volume of posts your combined subscriptions get each day (yellow) for the last 40 days, and how much of them you've still got marked unread (red). Enable it on the settings page, and use the URL to put into a widget or somewhere online like this:

twitter reddit linkedin facebook

RSS is far from dead!

2018-08-08 00:55  feeder  delphi internet freeware  [permalink]

I've been using RSS/Atom feeds on and off since I've learned about them. A long time ago, Google had a nice feed reader, but decided to discontinue it. Users were left to search something new, and I settled on The Old Reader, combined with gReader since I had a smartphone, and all was well. For a while. After some time you notice you still get disturbed by some tiny issues you can't seem to get to go away, either with tweaking the configuration or with Stylus. So what does a developer do? Start to think about developing their own solution. Then plan to develop their own solution. Then develop their own solution. So I'm somewhat proud to present this little thing I've been tinkering on in off-hours the last month:

github.com/stijnsanders/feeder

I have a live version to try out here: http://yoy.be/home/feeder/ but it uses the neighbouring instance of tx for authentication. I should enable Google/Facebook/Github OAuth things instead, but finding out how that works is a few items lower on my wish-list (of things I wished I had the time to put into).

I wanted a feed reader without the extra's. I wanted to mark items as read that move out of view by scrolling down, and plays somewhat nice with the surrounding HTML and the browser. For now I like how it works. There's an issue with emoji's that apparently get eaten by UTF8Decode, but that could be a bug that got solved since good old Delphi 7. But now that Delphi has a community edition, I think I should bring most if not all of my other projects to this version instead of sticking to Delphi 7... But that's another story. (One you might notice some time in the future on my Delphi RSS feed...)

twitter reddit linkedin facebook

How to do timezones?

2018-07-17 23:53  timezones  coding delphi weblog  [permalink]

I feel stupid. I guess I've been put out of my comfort zone. I was thinking about doing something, and then I did, and I thought I'll just primarily make it work for me, but then I noticed "new" items were still two hours behind. Ofcourse that's due to the bias against UTC we have here in my current local timezone. So there you have it. All my programming career, I would just parse dates, and stop before this "+0200" or "-0900" thing that's there at the end. So the right thing to do is go all the way, and with a little effort make it work correctly for not just me, but for any user of this little thing.

But how? I remember these drop-downs with timezones where I typically look-up Brussels or Paris. But it's summer daylight-saving-time for the moment. So it switches to and from only one hour between UTC twice a year (until policy changes), how do I keep track of that? Is there something that I can have the system do this automatically for me? It feels like these are things I should have known all along, but dont. I guess I'll have to start reading somewhere...

twitter reddit linkedin facebook

 

Archive... Search...