CSV Support

9 views
Skip to first unread message

Stuart Allen

unread,
Nov 6, 2011, 6:47:59 PM11/6/11
to jacl-discuss
Feel free to tell me I'm completely mad, but I've decided to add
support for reading and writing CSV files to JACL.

I had a friend who asked me to make a quick registration page for her
as a web form. I quickly looked at a book on Ruby on Rails and
thought, "you know, I can't be bothered learning all this" The end
result is some new functionality in JACL that lets you do this:

append data "sallen" "Stuart" "Allen" "stu...@email.com"

This command will write a line of CSV to the end of a file in the
'temp' directory (I may change that to a 'data' directory) that has
the name 'gamename-data.csv'

Automatically selecting the location, prefixing the name of the game
and the extension .csv are all designed to make it a bit safer from
hacking.

To read the data back in you use code like the following ('data' once
again indicates the root of the filename):

iterate data
set INDEX = 0
while INDEX < field_count
write field[INDEX] " "
set INDEX + 1
endwhile
write "^"
enditerate

The final command I want to make is an 'update' command that iterates
over the file in a similar way but requires you to re-write each line
as you iterate, thereby allowing you to modify the file in anyway you
see fit. This bit is a little bit tricky because I need it to be safe
to put on the web and have people make changes concurrently.

Regards,
Stuart

Thomas Schwarz

unread,
Nov 13, 2011, 5:18:28 PM11/13/11
to jacl-d...@googlegroups.com
Hi Stuart,

I started to experiment somewhat with the new csv support. And using the fcgijacl version I always get a segmentation fault when trying to use the "append" command, calling the csv_fwrite function from the libcsv.
Strangely if I use the cgijacl version with its own webserver then it works...
Do you have an idea, where the problem with calling libcsv from fcgijacl might come from?

(Working on Linux.)

Thanks!
Thomas

Stuart Allen

unread,
Nov 13, 2011, 5:45:11 PM11/13/11
to jacl-d...@googlegroups.com
Hi Thomas

I haven't done any testing with fcgijacl yet. Let me have a look today
and I'll see what is going on.

Also, I (think) I've finished a demo program called 'contacts.jacl'
for the CSV stuff. It is a simple web-based program for storing and
retrieving names and addresses.

Regards,
Stuart

--
http://dangarstu.tumblr.com

Stuart Allen

unread,
Nov 13, 2011, 6:39:25 PM11/13/11
to jacl-d...@googlegroups.com
Okay, looks like this is fixed. I was closing a NULL file pointer.
I'll look through the rest of the code to see if I do it anywhere
else.

Regards,
Stuart

--
http://dangarstu.tumblr.com

Stuart Allen

unread,
Nov 28, 2011, 4:41:56 AM11/28/11
to jacl-discuss
Thanks for pointing out that this still wasn't working Thomas, I'm
pretty sure it is now (although I've said that before haven't I!).

I had forgotten to use the special FastCGI replacements for the stdio
functions with fcgijacl.

Let me know if you still have any problems with it, I'm keen to get
this working properly.

Regards,
Stuart


On Nov 14, 10:39 am, Stuart Allen <stuartallen1...@gmail.com> wrote:
> Okay, looks like this is fixed. I was closing a NULL file pointer.
> I'll look through the rest of the code to see if I do it anywhere
> else.
>
> Regards,
> Stuart
>

> On 14 November 2011 09:45, Stuart Allen <stuartallen1...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > Hi Thomas
>
> > I haven't done any testing with fcgijacl yet. Let me have a look today
> > and I'll see what is going on.
>
> > Also, I (think) I've finished a demo program called 'contacts.jacl'
> > for the CSV stuff. It is a simple web-based program for storing and
> > retrieving names and addresses.
>
> > Regards,
> > Stuart
>

> > On 14 November 2011 09:18, Thomas Schwarz <schwarz.tho...@gmail.com> wrote:
> >> Hi Stuart,
>
> >> I started to experiment somewhat with the new csv support. And using the
> >> fcgijacl version I always get a segmentation fault when trying to use the
> >> "append" command, calling the csv_fwrite function from the libcsv.
> >> Strangely if I use the cgijacl version with its own webserver then it
> >> works...
> >> Do you have an idea, where the problem with calling libcsv from fcgijacl
> >> might come from?
>
> >> (Working on Linux.)
>
> >> Thanks!
> >> Thomas
>

> >> On Mon, Nov 7, 2011 at 12:47 AM, Stuart Allen <stuartallen1...@gmail.com>

Thomas Schwarz

unread,
Nov 28, 2011, 1:06:18 PM11/28/11
to jacl-d...@googlegroups.com
Hi Stuart,

while I am currently at incorporating all your latest changes into my version I noticed that you removed several commands like "article", "definite", "short", and some more from interpreter.c

By mistake? Or intentionally?

Regards,
Thomas

Stuart Allen

unread,
Nov 28, 2011, 9:09:40 PM11/28/11
to jacl-d...@googlegroups.com
Hi Thomas

Those commands were removed intentionally. The trouble with them is
that as soon as the details of objects can be modified with commands
like that their current state must be saved which gets horribly
inefficient, particular when a game is run on the web and the game is
saved after every move.

If you are looking at getting similar functionality more efficiently I
would be inclined to have an option similar to the 'long' property
where you can specify 'function' as the value and then have the text
generated by code rather than being static. This will give you dynamic
descriptions without the overhead of saving all the static text, even
though it never changes.

Stuart

--
http://dangarstu.tumblr.com

Thomas Schwarz

unread,
Nov 29, 2011, 1:26:11 AM11/29/11
to jacl-d...@googlegroups.com
Hi Stuart,

thanks for explaining. Makes sense!

Thomas

jaxom

unread,
Dec 8, 2011, 1:49:00 PM12/8/11
to jacl-discuss
Hi Stuart,

a little question about the CSV feature: (I already managed to use it
in my game, yeah!)

How would you handle it if you wanted each player to get his own data
file for something like his contacts for example?
Instead of "iterate data" would you say "iterate $user_id" or how
would you solve this? Because otherwise all users would all use the
same data file.

Thanks!
Thomas

Stuart Allen

unread,
Dec 8, 2011, 2:38:34 PM12/8/11
to jacl-d...@googlegroups.com
Hi Thomas

Yes, that should work. I've also been doing things like

string messages

setstring message "messg-" $user_id

iterate messages
...
enditerate

That was you can have separate data for each user and more than one
file for each user.

Take care,
Stuart

--
http://dangarstu.tumblr.com

Thomas Schwarz

unread,
Dec 8, 2011, 3:21:50 PM12/8/11
to jacl-d...@googlegroups.com
Hi Stuart,

fine!

Interesting what you are doing there. Messages. Sounds somewhat familiar ;-)

Thomas

Stuart Allen

unread,
Dec 8, 2011, 10:46:48 PM12/8/11
to jacl-d...@googlegroups.com
Hi Thomas

I just noticed I had the code in the interpreter a bit wrong for using
variables to build the filename so you are going to have to do an svn
update and recompile to get that code I posted to work.

Regards,
Stuart

--
http://dangarstu.tumblr.com

jaxom

unread,
Dec 13, 2011, 2:02:55 PM12/13/11
to jacl-discuss
Hi Stuart,

I have a problem with the iterate command as it seems.

The following code only displays
"ask_about_life: NOT LANGUAGE_DE"
from the first if/else construct. Nothing else.

The second conditional
>if player hasnt LANGUAGE_DE<
seems to evaluate to false or never to be reached because the line
write "ask_about_life: before if hasnt^"
even is not executed!?
The function seems to terminate before this.

May the "if else" in the "iterate" loop be a problem?

Here is the code:

integer wisdomselect 0
integer wisdomindex 0

{ask_about_life : ask_about_livings

if player has LANGUAGE_DE
write "ask_about_life: LANGUAGE_DE^"
else
write "ask_about_life: NOT LANGUAGE_DE^"
endif

if player has LANGUAGE_DE
write "Simon sagt: ~"
write " simonwisdomde = " simonwisdomde "^"
set max_rand = numsimonwisdomde
set wisdomselect = random
write " wisdomselect = " wisdomselect " Text = "
set wisdomindex = 0
iterate simonwisdomde
set wisdomindex + 1
if wisdomindex = wisdomselect
write field[0]
endif
enditerate
return
endif

write "ask_about_life: before if hasnt^"

if player hasnt LANGUAGE_DE
write "Simon says: ~"
write " simonwisdomen = " simonwisdomen "^"
set max_rand = numsimonwisdomen
set wisdomselect = random
write " wisdomselect = " wisdomselect " Text = "
set wisdomindex = 0
iterate simonwisdomen
set wisdomindex + 1
if wisdomindex = wisdomselect
write field[0]
endif
enditerate
endif
write "~^"
}


Thanks for help!

Regards
Thomas

On Nov 7, 12:47 am, Stuart Allen <stuartallen1...@gmail.com> wrote:

Stuart Allen

unread,
Dec 13, 2011, 6:14:20 PM12/13/11
to jacl-d...@googlegroups.com
Hi Thomas

This should be fixed now, it was a bug with having an iterate
statement inside an if statement that wasn't true. Let me know if it
gives you any more trouble.

Regards,
Stuart

--
http://dangarstu.tumblr.com

jaxom

unread,
Dec 19, 2011, 4:57:37 PM12/19/11
to jacl-discuss
Hi Stuart,

another question about the CSV feature. I want to store bigger sized
text content in a CSV file. I try to use a CSV file for storing for
example message board messages or help system texts. I noticed that my
texts get shortened when using the append command after typing them
into a textarea input box and submitting them as url/post parameters.
Is the problem the size of JACL strings or the size of URL parameters?
Or both?

Would it be sufficient to change the value size in the string_type to
for example 1024 instead of 256? I think not, because there are
several other variables, buffers, etc. involved handling strings and
so on...? It will be quite an effort to get bigger field sizes
working, right?

Regards
Thomas

On Nov 7, 12:47 am, Stuart Allen <stuartallen1...@gmail.com> wrote:

Stuart Allen

unread,
Dec 19, 2011, 10:49:13 PM12/19/11
to jacl-d...@googlegroups.com
Hi Thomas

There are some restrictions around the length of a URL (and the get
parameters included with it). You can read a bit about that here:
http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url

Using a POST form will get you around this restriction, but
unfortunately the test web server doesn't currently support POST
requests. I'm not sure how hard that would be to add, but without it
you would need to use FastCGI for all your testing or test with GET
and short parameters then turn on POST when you deploy.

It wouldn't be particularly hard to change the maximum length of a
JACL string from 256 to 1024 bytes. If you do a 'grep 255 *.c' you'll
see less than a screen's worth of output and even then not all hits
relate to the string length. The main reason I tried to keep them
small is that the strings are persisted at the end of each move, but
in this day and age writing out a few extra kilobytes of data isn't a
big deal.

So the upshot is you could change the length to 1024 pretty easily in
your multiplayer version, but I'll have a think about upsizing the
trunk version too.

Regards,
Stuart

--
http://dangarstu.tumblr.com

Thomas Schwarz

unread,
Dec 20, 2011, 1:14:56 AM12/20/11
to jacl-d...@googlegroups.com
Hi Stuart,

thanks for the info! So I think I will give it a try.

By the way, webjacl.c from the multiplayer branch is able to handle POST now for a long time already! ;-)

Regards
Thomas

Stuart Allen

unread,
Dec 20, 2011, 5:46:10 PM12/20/11
to jacl-d...@googlegroups.com
Hi Thomas

Let me know how you get on with the string length change.

How did you go about supporting POST requests? Is there much involved
in getting this to work? Also, do you experience the occassional
crashes with webjacl that I get? I have a friend lined up to help me
debug that soon.

Regards,
Stuart

--
http://dangarstu.tumblr.com

Thomas Schwarz

unread,
Dec 21, 2011, 1:04:24 AM12/21/11
to jacl-d...@googlegroups.com
Hi Stuart,

it really is not much:

I got it mainly by converting a POST to a GET (so to say) at the correct place for further handling.

    if(strstr(request, "POST") != NULL) {
        int length = 0;
       
        sscanf(contentlength, "Content-Length: %d", &length);
        //fprintf(stderr, "\nlength = %d\n", length);
        fgets(request_line, length+1, stdin);
        request_line[length] = '\0';
        sprintf(request, "GET ?%s", request_line);
        //fprintf(stderr, request);
      }

Just do a compare of your webjacl.c to the multiplayer branch version. You will see. No magic :-)

Regards
Thomas
Reply all
Reply to author
Forward
0 new messages