Jump to content

A cross-platform implementation of the AutoIt language


How interested are you?  

61 members have voted

  1. 1. How interested are you?

    • I am willing to work on the code
    • I am willing to help with testing
    • I would love to see this becoming a reality
    • Nah mate, I don't think this is a good idea


Recommended Posts

I really look forward to this, as this is a huge thing for me ease of transition wise to Linux... my go to programming language is always AutoIt... If It can be done in a 100 languages and AutoIt is one I go with it, as it's so easy to proto-type fast as well as get support when needed in a timely manner... as well as having the most experience in it!

Link to comment
Share on other sites

@rm4453 Thank you for showing the interest, I am planning to start work on this project soon... just need to finish something more important in life and once that is finished I can finally dedicate time to my hobby projects again :)

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

  • 2 months later...

@HansHenrik I am aiming for the former, but during the initial stages I might just directly use the abstract syntax tree skipping the bytecode for the sake of simplicity, which means it will effectively a text interpreter until the software is mature enough.

I really want to start work on this but I am having a hard time coming up with a name for the project :sweating:

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Do like with life: give birth to the baby and only then give him a name.

In the mean time use the placeholder XXX to keep excitation at high level.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Baby names:

CPA = Cross Platform Automator.
JSD = JavaScript for Desktops.
S = Sulfate ( Lightweight vs. Heavyweight / Aluminum vs. Iron / Sulfate vs. Rust ) 
G = the next language, because C,D,E,F names are taken :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

@jchd Thanks for the suggestion, I will think about it

@argumentum G is also taken.

4 hours ago, argumentum said:

JSD = JavaScript for Desktops.

Sounds like NodeJS :lol:

--

Seriously though, thanks for the suggestions, but I won't probably pick any generic or long names. I want it to be short and simple... ideally rhyming with AutoIt, I was thinking about ScriptIt but that was taken already... EasyScriptIt comes to mind but it is too long 😕

@TheSaint has submitted funny names like RabbIt, ManualIt, ForkIt etc. :muttley:

This reminds me of this quote: (Source)

Quote

There are only two hard things in Computer Science: cache invalidation and naming things.

-- Phil Karlton

 

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

4 hours ago, TheDcoder said:

@TheSaint has submitted funny names like RabbIt, ManualIt, ForkIt etc. :muttley:

Gawd, that is only the tip of the iceberg for all the names I have suggested ... you are hard to please. :wacko:

My favorite, is still ImagineIt ..... ha ha ha ha. Something we will be doing for a good while, especially if you get stuck on naming it. :lol:

TheDcoder and AutoIt had a baby, and it was called CoderIt ..... or Zit for short .... he got all the way through the alphabet, and then realized he had to pick something, so Z it is .... pronounced Zed It you pimple heads. I bet some of you thought it was named after a volcano ... well, maybe it was for a while, but then it got squeezed out of the running. :muttley:

So bud, any idea when Z++It will go into production? ;)

P.S. I believe AutoColdKey is still available ... though I guess AutoGoldKey would sound better and further from controversy. :lmao:

P.S.S. Maybe AutoIt and AutoHotkey had a baby and it was simply called AutoKey .... stranger things have happened. :P

Here's a growing shortlist for you.

Spoiler

AttempIt, CrackIt, CraftIt, BuildIt, DesignIt, EncodeIt, FormIt, GraftIt, MakeIt, MasterIt, ProduceIt, ProgramIt, StackIt, TestIt, UseIt, VentureIt, WieldIt, WriteIt

AutoBasic, Scripter, CodeWriter, Coder, CodeX, Cody, Funcle, Fungus

 

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

Okay, you doubting Thomases (male, female, etc).

If the following doesn't convince you that TheDcoder is the man for the job (this topic's idea), then nothing will.

Today, he came to me on HexChat with an issue. It is not an issue I had ever come across before, and even afterward I still did not see the issue ... clearly I'm not nerdy enough.

He was upset or bothered (plagued was his word) by the fact he was using the text "Start" twice in a script.

Here is the example code he gave me to illustrate the issue I was just not getting.

#include <GUIConstantsEx.au3>

Example()

Func Example()
    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 300, 200)

    ; Create a button control.
    Local $idButton = GUICtrlCreateButton("Start", 120, 170, 85, 25)
    Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    Local $bStarted = False

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Close
                ExitLoop
            Case $idButton
                $bStarted = Not $bStarted
                GUICtrlSetData($idButton, $bStarted ? "Stop" : "Start")
        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

He sent that to me in a PM to try and make things clearer.

He also said the following in the PM.

Quote

Notice how I use the string "Start" two times? First when creating the button and the next in the GUI loop. The goal is to accomplish the same functionality but with just one string, no duplicates in text.

Now I like to keep things simple, even if it takes more code and text. So I don't code like he does, and so rarely rely on False and True etc.

I've certainly never been guilty of using a line like the following. In fact I had to run it after he assured me it worked, to indeed see it does.

GUICtrlSetData($idButton, $bStarted ? "Stop" : "Start")

While I was checking that out, he thought I may have needed a simpler version, so he provided the following variant, but I had already sussed it out by then.

#include <GUIConstantsEx.au3>

Example()

Func Example()
    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 300, 200)

    ; Create a button control.
    Local $idButton = GUICtrlCreateButton("Start", 120, 170, 85, 25)
    Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    Local $bStarted = False

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Close
                ExitLoop
            Case $idButton
                $bStarted = Not $bStarted
                If $bStarted Then
                    GUICtrlSetData($idButton, "Stop")
                Else
                    GUICtrlSetData($idButton, "Start")
                EndIf
        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

Anyway, I was perplexed that he really found this an issue, so offered up the following solution, which worked, but did not satisfy him, and I am not surprised why ... I was just swapping one thing for another.

#include <GUIConstantsEx.au3>

Example()

Func Example()
    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 300, 200)
    Local $starttxt = "Start"
    Local $stoptxt = "Stop"

    ; Create a button control.
    Local $idButton = GUICtrlCreateButton($starttxt, 120, 170, 85, 25)
    Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    Local $bStarted = False

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Close
                ExitLoop
            Case $idButton
                $bStarted = Not $bStarted
                GUICtrlSetData($idButton, $bStarted ? $stoptxt : $starttxt)
        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

He then had a moment of genius, and came up with this.

#include <GUIConstantsEx.au3>

Example()

Func Example()
    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 300, 200)

    ; Create a button control.
    Local $idButton = GUICtrlCreateButton("Start", 120, 170, 85, 25)
    Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    ; Stop Text
    Local $sText = "Stop"

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Close
                ExitLoop
            Case $idButton
                GUICtrlSwapData($idButton, $sText)
        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

Func GUICtrlSwapData($idCtrl, ByRef $vSwapData)
    Local $vOldData = GUICtrlRead($idCtrl)
    GUICtrlSetData($idCtrl, $vSwapData)
    $vSwapData = $vOldData
EndFunc

To which I said the following.

Quote

You did all that complexity to avoid using the little string "Start".
Have you considered seeing a specialist?

To which he said.

Quote

Well bud, imagine many strings like that, and the amount of redundancy that would cause. I simply do not have it inside me to handle it, and being less-redundant is more important than being simple for me.

To which I said.

Quote

Gawd what redundancy. I fail to see a real world issue ... only some kind of nerdy one.

To which he said.

Quote

Maybe not, all geniuses have a bit of crazy in them. This is what makes them genius.

To which I said.

Quote

No wonder I have so many issues with nerds in the real world .... I rest my case.

To which he said.

Quote

Anyway bud, these are the kind of issues that I am plagued with.

To which I said.

Quote

Not exactly a real issue to my mind, so hard to see it as plagued.

To which he said.

Quote

The issue is as real as donald trump for me.

To which I said.

Quote

Then he must be a phantom .... fake person.

To which he laughed ... as I was doing.

I then said.

Quote

You are a Gen ASS bud, a true Genius of your generation. ha ha ha ha

And he is. :)

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

...not a bad exercise 

Spoiler
#include <GUIConstantsEx.au3>
Example()
Func Example()
    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 300, 200)

    Local $bStarted = Int(False), $aStarted[2] = ["Start","Stop"]

    ; Create a button control.
    Local $idButton = GUICtrlCreateButton($aStarted[$bStarted], 120, 170, 85, 25)
    Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Close
                ExitLoop
            Case $idButton
                $bStarted = Int(Not $bStarted)
                GUICtrlSetData($idButton, $aStarted[$bStarted])
        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

 

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

@argumentum Except that you're storing an integer in a variable that begins with a "b". I'm seeing red right now despite understanding why :D

Edited by seadoggie01

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

@TheSaint Thanks for sharing bud.

The script that I provided was a simplified example of what I was trying to do in C. Right now I am working on porting one of my programs (ProxAllium) to Linux, essentially re-writing it to work across platforms. I encountered this dilemma when I was writing the code for GUI, in C these kind of duplications have a bit more impact on future modification on code as it is a naturally low-level language, so it is best to write "clean" code from the start, as to avoid doing that in the future. Also, as no doubt most of you would have gotten the gist, I do not like redundancy in my code.

I actually tackled this problem in my AutoIt code as well, when working on the same program. At that time I came up with another solution: Using a dummy value and artificially trigger the toggle code so that it can properly populate the correct value, I even found a "hack" in AutoIt which lets me kind of simulate GUI events (when using OnEvent mode):

Also containing a code example, which practically does the same thing as the previous examples:

Spoiler
; This snippet will show you a "hack" that you can use in GUI OnEvent mode in AutoIt
; With this hack you can create fake/pseudo events for a control in a OnEvent "handler"
; function which is registered with multiple controls.

; Usually you can get around this by using a unique function for every control
; but I like to use a single function that I use as a handler for a group of related
; controls. Looks neat and organized :)

; Let's get started!

; Include the important stuff
#include <AutoItConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt("GUIOnEventMode", 1)

; This function will create the GUI and make it visible
Func CreateGUI()
    GUICreate("Example", 60, 60)
    ; Functions with parameters will not be called, unless all of their parameters are optional (undocumented)
    GUISetOnEvent($GUI_EVENT_CLOSE, HandleGUI)
    Global $idToggleButton = GUICtrlCreateButton("", 5, 05, 50, 50)
    GUICtrlSetOnEvent($idToggleButton, HandleGUI)
EndFunc

; This is our most important piece of code, the Handler function which handles
; any events generated by the GUI!
Func HandleGUI($iCtrlID = Default)
    ; As mentioned previously, when a function is called by AutoIt's OnEvent handler,
    ; the optional parameters are NOT defined at all! So their default values are meaningless
    ; Therefore we can use IsDeclared to see if a parameter is declared, effective way to know
    ; if it was called by AutoIt's OnEvent handler.
    ;
    ; The switch expression is a ternary operation, it first checkes if $iCtrlID is defined,
    ; then if it is declared locally, the expression is evaluated to $iCtrlID's value. This
    ; would be the case when a psedo/fake event has been generated by the script manually
    ;
    ; If it was called by AutoIt, then the expression would evaluate to @GUI_CtrlID
    ;
    ; This allows for seamless integration with the code, you won't have to use ControlClick to
    ; create a mouse press or something similar!
    Switch (IsDeclared("iCtrlID") = $DECLARED_LOCAL ? $iCtrlID : @GUI_CtrlId)
        Case $GUI_EVENT_CLOSE
            Exit
        Case $idToggleButton
            Local Static $bOn = True
            If $bOn Then
                GUICtrlSetData($idToggleButton, "Off")
                $bOn = False
            Else
                GUICtrlSetData($idToggleButton, "On")
                $bOn = True
            EndIf
    EndSwitch
EndFunc

; A practical use case:
; Often when there is a button which toggles/switches between values, the default value will have
; to be repeated when creating the control, this is fine for small things but is a good way to do
; if you have something more that needs to be done. This is just a simple example of a button which
; toggles between On and Off. The speciality is that those values will not be repeated in the code :)
;
; This is not very easy to read or as simple as setting the value of the button to the default state
; during the creation of the GUI, but it is a good practise that helps you avoid replicating text

CreateGUI()

HandleGUI($idToggleButton) ; This will generate a fake event which will trigger the same action as clicking on the button

GUISetState() ; Show the GUI

While True
    Sleep(10)
WEnd

; Link to this code snippet on Gist: https://git.io/vbRQ5

 

@argumentum An interesting and out-of-the-box solution, kudos, I may even find an use for it :)

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Hello everyone,

Just a small but important update, as of today I have officially started work on the project, and I have chosen to name it EasyCodeIt :)

There are a handful of reasons why I chose that name:

  1. It reflects one of the important goals, keeping it easy to code
  2. It somewhat makes sense and rhymes with AutoIt
  3. By far, it is the only name which hasn't been used by others (DuckDuckGo shows that no results contain that word)
  4. It is shorter than other potential names while still being meaningful :lol:
  5. ...there might be other reasons which I cannot recall right now

If I come across a better name, I might change it still, so nothing is set in concrete.

I am licensing the code under GPL (v3), a newer version of the same license under which AutoIt3 used to be under. I don't really have a problem with others forking my code, but I sure do not want the forks to be closed source, that is the reason why I did not choose a 100% free license. Eventually we would need exceptions down the road to allow binary distribution of executable without having to require disclosing their own source code.

My current aim is to build a bare-minimum cross-platform interpreter which can act as a proof-of-concept, and we can build from there :D

I will release the code publicly once I actually finish something presentable, right now my code is not very different than a simple imitation of command-line tools like cat or type :muttley:

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

I think regular progress reports might be a good idea, it will help keep my motivation afloat :)

Today I read some stuff about parsing, scanning (lexical analysis) etc., but nothing really note-worthy. I still don't have a good idea on the overall design of the code... but I have the big picture in mind, and I guess the code will naturally evolve as I work on it.

The first major-ish hurdle is actually reading the code from the file, I was thinking about loading the whole thing into memory as it sounds simple, but I found out that there are not standard C functions to reliably calculate the size of the total stuff in a file, so not very easy unless I resort to platform-specific API.

An alternative and in my opinion a better method is to buffer the file, only keeping a part of it in memory. It is pretty easy to do, but the problem arises when we have to work near the boundaries, where a token might be split unevenly.

It is 5 AM here right now and I should really head to sleep, my sleep schedule is a bit messed up at the moment :blink:

Bye!

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

What I really want to know, which is by far the most important aspect of all this right now.

Do I need one big bag of popcorn .... or several .... while you work on ImagineIt? :blink:

Spoiler

:muttley: Just kidding bud. Love your chosen name of EasyCodeIt, and best of luck with your deliberations and enterprise. :)

I will be watching and waiting ...... like Big Brother perhaps ... or your Dad ... or just an interested party, amazed at your going-ons. :lol:

WhipIt ..... whip it good .... into shape that is. Crack that whip! :P

P.S. I just put an order in for a truckload .... of popcorn that is. I'm here for the long haul. :whistle:

 

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

On 6/8/2020 at 11:39 AM, TheDcoder said:

Just a small but important update, as of today I have officially started work on the project, and I have chosen to name it EasyCodeIt :)

I was rooting for "Doughnut Script", but I guess that would have just made TheSaint hungry every time he read the project updates.

Link to comment
Share on other sites

20 minutes ago, willichan said:

I was rooting for "Doughnut Script", but I guess that would have just made TheSaint hungry every time he read the project updates.

DonutIt or DoughnutIt has a nice ring (sic) to it .... and rolls off the tongue ... quite a tasty title. DognutIt. :muttley:

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

On 6/10/2020 at 5:10 AM, TheDcoder said:

It is 5 AM here right now and I should really head to sleep

Alas, I never slept, decided that I should just get up and use it as a leap day to reset my schedule. I slept at 8 PM on that day and woke-up at ~3 AM today, I did some nice work on a function to read the contents of a file but had to stop due to a rather long power outage.

Eventually I got a bit tired after breakfast and decided to take a nap around 6-7 AM, that turned out to be a bad decision, as I ended up sleeping/laying in bed for 6 hours! It was just the perfect temperature with cool air and my warm bed, so I couldn't manage to get up even though I was a bit awake.

So I did not have much time for coding today. I managed to get my function to a working state:

The idea behind the function is that it will read the contents of the file in chunks by using a linked list and then concatenate all of those chunks into a big buffer which is a lot easier to work with. Here is the code for those who are interested, note that it has some rough edges and can be optimized further:

Spoiler

#ifndef READ_FILE_BUFFER_SIZE
#define READ_FILE_BUFFER_SIZE 1024
#endif

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"

struct ReadFileBufferNode {
	char buffer[READ_FILE_BUFFER_SIZE + 1];
	size_t data_len;
	struct ReadFileBufferNode *next;
};

char *readfile(FILE *file) {
	// Define the final buffer
	char *final_buffer = NULL;
	
	// Define and allocate the initial node
	struct ReadFileBufferNode *initial_node = malloc(sizeof(struct ReadFileBufferNode));
	if (!initial_node) return NULL;
	
	// Read the contents of file in chunks
	struct ReadFileBufferNode *curr_node = initial_node;
	struct ReadFileBufferNode *next_node;
	while (true) {
		// Copy the current chunk
		char *success = fread(curr_node->buffer, READ_FILE_BUFFER_SIZE + 1, file);
		if (!success) {
			// Check if we have hit EOF
			int end = feof(file);
			if (!end) goto cleanup;
			
			// Mark this node as empty
			curr_node->data_len = 0;
			curr_node->next = NULL;
			
			// Break the loop
			break;
		}
		// TODO: Don't use strlen
		curr_node->data_len = strlen(curr_node->buffer);
		
		// Allocate the next buffer node
		next_node = malloc(sizeof(struct ReadFileBufferNode));
		if (!next_node) goto cleanup;
		curr_node->next = next_node;
		curr_node = next_node;
	}
	
	// Calculate final size
	// TODO: Integrate it into reading
	size_t final_size = 0;
	curr_node = initial_node;
	do {
		final_size += curr_node->data_len;
		curr_node = curr_node->next;
	} while (curr_node);
	
	// Allocate the buffer
	final_buffer = malloc(final_size + 1);
	if (!final_buffer) goto cleanup;
	final_buffer[final_size] = '\0';
	
	// Copy data into the final buffer
	curr_node = initial_node;
	char *curr_chunk = final_buffer;
	do {
		memcpy(curr_chunk, curr_node->buffer, curr_node->data_len);
		curr_chunk += curr_node->data_len;
		curr_node = curr_node->next;
	} while (curr_node);
	
	// Free all nodes
	cleanup:
	curr_node = initial_node;
	do {
		next_node = curr_node->next;
		free(curr_node);
		curr_node = next_node;
	} while (curr_node);
	
	// Return the final buffer
	return final_buffer;
}

 

It is 8:20 PM now, so I better go and sleep soon. Later guys :)

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Alright, I finished work on the readfile function, looks pretty solid to me :)

/*
 * MIT License
 * 
 * Copyright (c) 2020 Damon Harris <TheDcoder@protonmail.com>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef READ_FILE_BUFFER_SIZE
#define READ_FILE_BUFFER_SIZE 1024
#endif

struct ReadFileBufferNode {
	char buffer[READ_FILE_BUFFER_SIZE];
	size_t data_len;
	struct ReadFileBufferNode *next;
};

/// @brief Read the contents of a text file into a dynamically allocated buffer efficiently
/// @details This function reads the file in chunks which are stored in a linked list, and then all of the chunks are concatenated
///          into a single buffer which perfectly fits the whole string.
/// @author Damon Harris (TheDcoder@protonmail.com)
/// @param [in] file Pointer to the FILE to read.
/// @returns If success, pointer to dynamically allocated buffer containing the full contents of the file, NULL otherwise in case of an error.
char *readfile(FILE *file) {
	// Define the final buffer
	char *final_buffer = NULL;
	size_t final_size = 0;
	
	// Define and allocate the initial node
	struct ReadFileBufferNode *initial_node = malloc(sizeof(struct ReadFileBufferNode));
	if (!initial_node) return NULL;
	
	// Read the contents of file in chunks
	struct ReadFileBufferNode *curr_node = initial_node;
	struct ReadFileBufferNode *next_node;
	while (true) {
		// Copy the current chunk
		size_t bytes_read = fread(curr_node->buffer, 1, READ_FILE_BUFFER_SIZE, file);
		curr_node->data_len = bytes_read;
		final_size += bytes_read;
		if (bytes_read < READ_FILE_BUFFER_SIZE) {
			// Check if we have an error
			if (ferror(file)) goto cleanup;
			
			// Mark this node as final
			curr_node->next = NULL;
			
			// Break the loop
			break;
		}
		
		// Allocate the next buffer node
		next_node = malloc(sizeof(struct ReadFileBufferNode));
		if (!next_node) goto cleanup;
		curr_node->next = next_node;
		curr_node = next_node;
	}
	
	// Allocate the buffer
	final_buffer = malloc(final_size + 1);
	if (!final_buffer) goto cleanup;
	final_buffer[final_size] = '\0';
	
	// Copy data into the final buffer
	curr_node = initial_node;
	char *curr_chunk = final_buffer;
	do {
		memcpy(curr_chunk, curr_node->buffer, curr_node->data_len);
		curr_chunk += curr_node->data_len;
		curr_node = curr_node->next;
	} while (curr_node);
	
	// Free all nodes
	cleanup:
	curr_node = initial_node;
	do {
		next_node = curr_node->next;
		free(curr_node);
		curr_node = next_node;
	} while (curr_node);
	
	// Return the final buffer
	return final_buffer;
}

I can now *finally* begin work on the parser, will do that later today :D

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...