Trying to reduce memory usage

2021-02-11 Thread Josh via Digitalmars-d-learn
I'm trying to read in a text file that has many duplicated lines 
and output a file with all the duplicates removed. By the end of 
this code snippet, the memory usage is ~5x the size of the infile 
(which can be multiple GB each), and when this is in a loop the 
memory usage becomes unmanageable and often results in an 
OutOfMemory error or just a complete lock up of the system. Is 
there a way to reduce the memory usage of this code without 
sacrificing speed to any noticeable extent? My assumption is the 
.sort.uniq needs improving, but I can't think of an easier/not 
much slower way of doing it.


Windows 10 x64
LDC - the LLVM D compiler (1.21.0-beta1):
  based on DMD v2.091.0 and LLVM 10.0.0

---

auto filename = "path\\to\\file.txt.temp";
auto array = appender!(string[]);
File infile = File(filename, "r");
foreach (line; infile.byLine) {
  array ~= line.to!string;
}
File outfile = File(stripExtension(filename), "w");
foreach (element; (array[]).sort.uniq) {
  outfile.myrawWrite(element ~ "\n"); // used to not print the \r 
on windows

}
outfile.close;
array.clear;
array.shrinkTo(0);
infile.close;

---

Thanks.


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Josh via Digitalmars-d-learn

On Monday, 20 May 2019 at 11:10:32 UTC, Boqsc wrote:

https://dlang.org/spec/float.html

I'm frozen in learning basics of D lang since I want to create 
a simple game and I really would like a clean and simple code, 
however to me floating points are magic.


https://wiki.dlang.org/Review_Queue
Since std.decimal is still work in progress and apparently its 
development is stuck for a while, should I just somehow use 
floating point to store currency or wait until Decimal package 
will be finally included into std Phobos of D lang?


Normally I would say no, no and no.  Rounding issues will kill 
you every time.  However:


import std.stdio;
import std.range;

void main()
{
foreach (i; iota(1, 1000)) {
writefln("%f", cast(float) i / 100.0);
}
}

Doesn't show any rounding issues, but you still might hit them at 
large values...I just remember back in the day having numbers 
like 0.199, but maybe that problem has been solved.


What would be safer is to do "fixed point" math, i.e. use an 
integer and when displaying the value convert it to float and 
divide by 100.  So if the user has 50 cents they internal value 
would be 50, if you give them a dollar twenty five (125) then 
they would have 175, and when you go to display it, dividing by 
100 will display 1.75.


As long as you are not multiplying money by money you will be 
fine.  50 cents times 5 is 2.50 (50 * 5 = 250), however 50 cents 
times 50 cents is 2500, which makes no sense but so does 
multiplying money by money...




Re: Linked List iterating over and inserting an element around (before/after) the current position.

2019-05-19 Thread Josh via Digitalmars-d-learn

Thank you, that helps big time.

This is just more curiosity, but do you happen to know why I have 
to use DList.linearRemove() instead of DList.remove()?


import std.stdio;
import std.container.dlist;
import std.algorithm;
import std.range;

void main()
{
auto list = make!DList("the", "quick", "brown", "fox");
auto range = list[].find("quick").take(1);
list.remove(range);
list[].each!writeln; // the brown fox
}

This results in a compiler issue:

onlineapp.d(10): Error: function 
std.container.dlist.Container!string.DList.remove(Range r) is not 
callable using argument types (Take!(Range))
onlineapp.d(10):cannot pass argument range of type 
Take!(Range) to parameter Range r


Changing "remove" to "linearRemove" fixes it, but both the remove 
and linearRemove functions take a Range object, and linearRemove 
seems to just be a pass through to remove.




Linked List iterating over and inserting an element around (before/after) the current position.

2019-05-19 Thread Josh via Digitalmars-d-learn
Just started looking at D this weekend, coming from a 
C++/Java/Go/Rust background and it's really not going well.  
Trying to write something to play with the language and need a 
linked list, looking in std.container you have a single or doubly 
linked list...great.


Now how to I iterate over it and look for a value and then modify 
it, and maybe insert a new element before or after that 
element.After spending way to long on the API realized I need 
to be looking at std.range (I think, maybe not, I'm not sure).


So off to the std.range documentation, which recommended reading 
http://ddili.org/ders/d.en/ranges.html, okay read that, boy if I 
want to display the contents of range I'm ALL set, to bad I would 
like to modify a list, so I seem to be no closer to my goaloh 
and by the way if you think:


import std.stdio;
import std.range;

void main() {
int[] slice = [ 1, 2, 3 ];
int[] slice2 = slice;

put(slice2, 100);

writeln(slice2);
writeln(slice);
}

Resulting in:

[2, 3]
[100, 2, 3]← expected result

Is obvious, I have some bad news for you.

Now I'm thinking maybe std.algorithm.comparison, maybe iteration 
or maybe mutation seems promising, at least that's what I want to 
do, mutate a listhey there is a swap...oh it doesn't deal 
with ranges...


Maybe swapAt but that sounds like I need an index, and indexes 
with linked list don't really perform well...but it does take a 
rangeokay I think that is what I need, so in a foreach loop, 
looking at https://tour.dlang.org/tour/en/basics/ranges I would 
call swapAt and pass in __rangeCopy, I think I can update, happy 
days, now to figure out how to add something before or after that 
element..



So in short I guess my complaint is that you show all this stuff 
about displaying ranges and removing items from the front or 
end...so if I want a queue we're set, but nothing about modifying 
them...unless it's so blatantly obvious I'm just missing it, 
which could be the case.




Trying to extract string from curl redirected URL

2019-02-10 Thread Josh via Digitalmars-d-learn
I have a website (say https://website.com) that I need to log in 
to, it will do a few 302 redirects and then I will end up with a 
unique session ID in the URL (such as 
https://website.com/welcome.html?s=636853677441448706). Is there 
some way of extracting this ID (I'll need it later for other 
things)?


I'm using std.net.curl's HTTP, and when I turn verbose on and do 
the login POST I can see that it is in fact redirecting to the 
URL with the session ID. I can see that etc.c.curl has 
CurlInfo.effective_url and CurlInfo.redirect_url that I can use 
with curl_easy_getinfo, but that needs a CURL*. 
HTTP.handle.handle is private, so I can't get a CURL* out of the 
Curl struct.


Is there something I'm missing? It it possible to access the 
private handle? Is there a better way to do what I'm trying to 
achieve?


Re: libcurl acting differently to curl.exe

2017-12-10 Thread Josh via Digitalmars-d-learn

The POST C code was:

/* Sample code generated by the curl command line tool 
**

 * All curl_easy_setopt() options are documented at:
 * https://curl.haxx.se/libcurl/c/curl_easy_setopt.html
 
/

#include 

int main(int argc, char *argv[])
{
  CURLcode ret;
  CURL *hnd;

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "https://foo.com/logon.php;);
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, 
"username=user=pass=submit");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, 
(curl_off_t)52);

  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.57.0");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, 
(long)CURL_HTTP_VERSION_2TLS);
  curl_easy_setopt(hnd, CURLOPT_CAINFO, 
"C:\\Users\\Josh\\Downloads\\curl-7.57.0-win64-mingw\\bin\\curl-ca-bundle.crt");
  curl_easy_setopt(hnd, CURLOPT_SSH_KNOWNHOSTS, 
"C:\\Users\\Josh\\AppData\\Roaming/_ssh/known_hosts");

  curl_easy_setopt(hnd, CURLOPT_COOKIEFILE, "cookie.dat");
  curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "cookie.dat");
  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get 
generated
 as source easily. You may select to either not use them or 
implement

 them yourself.

  CURLOPT_WRITEDATA set to a objectpointer
  CURLOPT_INTERLEAVEDATA set to a objectpointer
  CURLOPT_WRITEFUNCTION set to a functionpointer
  CURLOPT_READDATA set to a objectpointer
  CURLOPT_READFUNCTION set to a functionpointer
  CURLOPT_SEEKDATA set to a objectpointer
  CURLOPT_SEEKFUNCTION set to a functionpointer
  CURLOPT_ERRORBUFFER set to a objectpointer
  CURLOPT_STDERR set to a objectpointer
  CURLOPT_DEBUGFUNCTION set to a functionpointer
  CURLOPT_DEBUGDATA set to a objectpointer
  CURLOPT_HEADERFUNCTION set to a functionpointer
  CURLOPT_HEADERDATA set to a objectpointer

  */

  ret = curl_easy_perform(hnd);

  curl_easy_cleanup(hnd);
  hnd = NULL;

  return (int)ret;
}
/ End of sample code /



libcurl acting differently to curl.exe

2017-12-10 Thread Josh via Digitalmars-d-learn
I'm trying to use libcurl in D to download a page that requires 
logging in first. At the moment though, I can't even get the 
logging in working. I tried with curl.exe, got it working, and 
used the --libcurl command to export C code that I then turned 
into (I think) equivalent D code.


The problem is that when I POST the login form, curl.exe gets a 
HTTP 200 to the correct page, whereas libcurl gets a HTTP 302 
back to the login page, which is the same behaviour I noticed 
when cookies weren't being saved/reused.


I've tried with the HTTP struct functions, and also setting curl 
options explicitly like the C code does. Is there something I've 
missed?


import std.file;
import std.net.curl;
import std.stdio;

void main() {
getLogon();
postLogon();
getIndex();
}

void getLogon()
{
auto http = HTTP();
	http.onReceive = (ubyte[] data) { /+ drop +/ 
std.file.write("logon1.html", data); 
/+writeln(cast(char[])(data)); stdout.flush;+/ return 
data.length; };


http.handle.set(CurlOption.tcp_nodelay, 1);
http.handle.set(CurlOption.buffersize, 102400);
http.handle.set(CurlOption.noprogress, 1);
//http.handle.set(CurlOption.useragent, "curl/7.57.0");
http.handle.set(CurlOption.maxredirs, 50);
	//http.handle.set(CurlOption.cainfo, 
"C:\\Users\\Josh\\Downloads\\curl-7.57.0-win64-mingw\\bin\\curl-ca-bundle.crt");

http.handle.set(CurlOption.cookiejar, "cookie.dat");
http.handle.set(CurlOption.cookiefile, "cookie.dat");
http.handle.set(CurlOption.verbose, 1);

http.handle.set(CurlOption.url, "https://foo.com/logon.php;);
http.method(HTTP.Method.get);

http.perform();
}

void doLogon()
{
auto http = HTTP();
	http.onReceive = (ubyte[] data) { /+ drop +/ 
std.file.write("logon2.html", data); 
/+writeln(cast(char[])(data)); stdout.flush;+/ return 
data.length; };


http.handle.set(CurlOption.tcp_nodelay, 1);
http.handle.set(CurlOption.buffersize, 102400);
http.handle.set(CurlOption.noprogress, 1);
//http.handle.set(CurlOption.useragent, "curl/7.57.0");
http.handle.set(CurlOption.maxredirs, 50);
	//http.handle.set(CurlOption.cainfo, 
"C:\\Users\\Josh\\Downloads\\curl-7.57.0-win64-mingw\\bin\\curl-ca-bundle.crt");

http.handle.set(CurlOption.cookiejar, "cookie.dat");
http.handle.set(CurlOption.cookiefile, "cookie.dat");
http.handle.set(CurlOption.verbose, 1);

http.handle.set(CurlOption.url, "https://foo.com/logon.php;);
	http.handle.set(CurlOption.postfields, 
"username=user=pass=submit");

http.handle.set(CurlOption.postfieldsize_large, 52);
http.method(HTTP.Method.post);

http.perform();
}

void getIndex()
{
auto http = HTTP();
	http.onReceive = (ubyte[] data) { /+ drop +/ 
std.file.write("index.html", data); 
/+writeln(cast(char[])(data)); stdout.flush;+/ return 
data.length; };


http.handle.set(CurlOption.tcp_nodelay, 1);
http.handle.set(CurlOption.buffersize, 102400);
http.handle.set(CurlOption.noprogress, 1);
//http.handle.set(CurlOption.useragent, "curl/7.57.0");
http.handle.set(CurlOption.maxredirs, 50);
	//http.handle.set(CurlOption.cainfo, 
"C:\\Users\\Josh\\Downloads\\curl-7.57.0-win64-mingw\\bin\\curl-ca-bundle.crt");

http.handle.set(CurlOption.cookiejar, "cookie.dat");
http.handle.set(CurlOption.cookiefile, "cookie.dat");
http.handle.set(CurlOption.verbose, 1);

http.handle.set(CurlOption.url, "https://foo.com/index.php;);
http.method(HTTP.Method.get);

http.perform();
}

libcurl verbose dump: https://pastebin.com/Sq60CLHV
curl.exe verbose dump: https://pastebin.com/KBDDNq9k

Thanks,

Josh


Re: Problems with function as parameter

2017-09-21 Thread Josh via Digitalmars-d-learn

On Friday, 22 September 2017 at 03:26:36 UTC, Mike Parker wrote:

On Friday, 22 September 2017 at 02:22:46 UTC, Josh wrote:



src\mixer.d(80,22): Error: function pointer 
Mix_ChannelFinished (extern (C) void function(int channel)) is 
not callable using argument types (extern (C) void 
delegate(int channel))


Code:
void unmuteAfterPlaySound()
{
Mix_ChannelFinished();
}

extern (C) void channelDone(int channel)
{
unmuteMusic();
}


The error message indicates that `channelDone` is a member of a 
class or a struct. A pointer to a member function is a delegate 
(or closure), not a function pointer. Free functions, static 
nested functions, and static member functions all produce 
function pointer. Non-static member functions and non-static 
nested functions all produce delegates/closures. See the docs:


https://dlang.org/spec/function.html#closures

If you need to manipulate instance members from a C callback, 
you'll need a way to implement a mechanism to work out which 
instance you need.


Perfect, that's the info I needed. As these functions were in a 
class, setting channelDone and unmuteMusic to static worked.


As an aside, in that doc it says "The .funcptr property of a 
delegate will return the function pointer value as a function 
type". So I also tried 
Mix_ChannelFinished(().funcptr); and this compiled, 
but caused a segfault when
the callback ran. What would have caused this? Is it because it's 
a C function?


Re: Problems with function as parameter

2017-09-21 Thread Josh via Digitalmars-d-learn

On Friday, 22 September 2017 at 02:18:34 UTC, Mike Parker wrote:
On Thursday, 21 September 2017 at 22:05:22 UTC, Matt Jones 
wrote:

On Thursday, 21 September 2017 at 20:21:58 UTC, Josh wrote:
I'm trying to write a callback function for SDL_mixer through 
Derelict, but this is the first time I've tried to use a 
function as a parameter, and so I think I'm just making a 
minor mistake somewhere.


[...]


Make it a C function, not a D function:

extern (C) void channelDone(int channel)
{
unmuteMusic();
}

and use & to reference the function instead of calling it:

Mix_ChannelFinished();


It should be extern(C) and, ideally, nothrow. The binding 
should be enforcing nothrow, but currently doesn't. I'll change 
that now.


Why should the binding force nothrow? I don't understand why you 
HAVE to not throw exceptions. Is it because of the C -> D aspect?


Re: Problems with function as parameter

2017-09-21 Thread Josh via Digitalmars-d-learn

On Thursday, 21 September 2017 at 22:05:22 UTC, Matt Jones wrote:

On Thursday, 21 September 2017 at 20:21:58 UTC, Josh wrote:
I'm trying to write a callback function for SDL_mixer through 
Derelict, but this is the first time I've tried to use a 
function as a parameter, and so I think I'm just making a 
minor mistake somewhere.


[...]


Make it a C function, not a D function:

extern (C) void channelDone(int channel)
{
unmuteMusic();
}

and use & to reference the function instead of calling it:

Mix_ChannelFinished();


Thanks for the help, but when I try that, I get:

src\mixer.d(80,22): Error: function pointer Mix_ChannelFinished 
(extern (C) void function(int channel)) is not callable using 
argument types (extern (C) void delegate(int channel))


Code:
void unmuteAfterPlaySound()
{
Mix_ChannelFinished();
}

extern (C) void channelDone(int channel)
{
unmuteMusic();
}


Problems with function as parameter

2017-09-21 Thread Josh via Digitalmars-d-learn
I'm trying to write a callback function for SDL_mixer through 
Derelict, but this is the first time I've tried to use a function 
as a parameter, and so I think I'm just making a minor mistake 
somewhere.


The C SDL docs say:

// make a channelDone function
void channelDone(int channel)
{
printf("channel %d finished playing.\n", channel);
}
...
// set the callback for when a channel stops playing
Mix_ChannelFinished(channelDone);


And my D code is:

void unmuteAfterPlaySound()
{
Mix_ChannelFinished(channelDone);
}

void channelDone(int channel)
{
unmuteMusic();
}


But DMD seems to be trying to run channelDone() i.e. with no 
parameters and parentheses omitted, and is giving this error:


Error: function Mixer.channelDone (int channel) is not callable 
using argument types ()
Error: function pointer Mix_ChannelFinished (extern (C) void 
function(int channel)) is not callable using argument types 
(_error_)


Is anyone able to see what I've done wrong? Any help would be 
appreciated, thanks.


Starting threads inside class

2016-02-23 Thread Josh via Digitalmars-d-learn
My goal with the code below is to eventually have my main 
communicate with Foo and Bar classes listening for packets on a 
different address/port, each in a separate thread. They would 
then communicate with Foobaz and Barbaz threads respectively to 
do other work. In trying to get just Foo working though, I'm 
getting this error:


Error: template std.concurrency.spawn cannot deduce function from 
argument types !()(void delegate(Tid ownerTid), Tid), candidates 
are:
D:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(466):
std.concurrency.spawn(F, T...)(F fn, T args) if 
(isSpawnable!(F, T))


The code works fine if I call daemon as a normal function, but it 
holds up the main thread.


Is there anything I'm doing wrong here? I'm not accessing 
anything outside this class from inside, and the most I would be 
doing from outside is accessing the Tid in order to send packets 
from my main.


class Foo
{
private string address = "127.0.0.1";
private ushort port = 5;
private ubyte[256] buffer;
private TcpSocket mysock;
Tid listenerd;

this()
{
listenerd = spawn(, thisTid);
}

void setup()
{
mysock = new TcpSocket();
mysock.blocking = true;
try
{
mysock.connect(new InternetAddress(address, port));
}
catch (SocketOSException e)
{
}
}

void initialise()
{
// send init packet
}

void closeConnection()
{
// send close packet
}

void packetHandler()
{
// do something with buffer
}

void daemon(Tid ownerTid)
{
setup();
initialise();
int rxSize = -1;
while (true)
{
rxSize = mysock.receive(buffer);
if (rxSize == 0)
{
break;
}
packetHandler();
}
closeConnection();
}
}