Archive

Archive for February 3, 2015

TQTXReader and TQTXWriter for Smart Mobile Studio

February 3, 2015 Leave a comment

Storage has become a theme the past couple of weeks for Smart Mobile Studio. I have posted twice about the filesystem classes I have added to QTX, but I have also added more – much more! As you will see over the next weeks 🙂

Whenever you need to write or read data, you really end up with variants in HTML5. Javascript has this thing where everything is either an object (read: prototypical object) an array, or an intrinsic value. To make writing and reading named value pairs easier I have created two classes, cleverly called TQTXReader and TQTXWriter.

Propertybag's are fun!

Propertybag’s are fun!

The writer allows you to, well.. write into a buffer (managed by the class). Like this:

var mObj:=TQTXWriter.Create(null);
try
  mObj.writeStr("first-name",edFirstname.text);
  mobj.writeStr("last-name",edLastName.text);
  mObj.writeStr("cardID",edVisa.text);

  CallCardLookup(mObj.Deserialize, procedure ()
    begin
      showmessage("Visa card is valid");
    end);
finally
  mObj.free;
end;

And TQTXReader does the exact same, but in reverse. The constructor can take a variant containing the information you want to read (stored with TQTXWriter) and extract info in the same way.

Practical uses

Loads! You can use it to tailor custom messages to be used with the spanking new message-api. That way you don’t have to fiddle with JObject based classes. Serialize() and Deserialize() are the methods for turning the data into a string and back again.

You can use it to avoid strictly typed records, which can be handy – especially for grid designs and/or “flexible” arrays of content. But please remember that Serialize() and Deserialize() are costly in terms of speed.

It’s also perfect to interface with JS libraries which expects name-value pairs in constructors and setup routines.

But word to the wise – if all you need is a one-shot wonder, then TQTXWriter is overkill. In such a case you can get away with an anonymous record:

  Fhandle.setupJS( record
     mouse  := "yes";
     startX := 100;
     startY := 100;
   end);

HTML5 Filesystem in Smart Mobile Studio

February 3, 2015 Leave a comment

Yesterday I presented a new QTX feature, namely a virtual filesystem which runs in your browser. In short it allows you to create files through an in-memory filesystem, which can then be stored in its totality in local-storage, global-storage or in a browser database.

Well today I can show you an example of how you use this. Here is a short teaser. Notice the use of anonymous records, which is really a fantastic feature of Smart Pascal.

    mFileSystem:=TQTXFileSystem.Create(NIL);
    try
      mFileSystem.mkDir('first')
        .mkDir('second')
        .mkFile('text.txt',null);

      mFile:=TQTXFileSystemFile(mFileSystem.FindFileObject
        ('/first/second/text.txt'));

      if mFile<>NIL then
      begin

        mFile.WriteData
        ( record
            id:= 12;
            text:= "this is awesome";
            cost:= 12.95
          end);

        writeln(mFile.ReadData.text);
      end else
      writeln('invalid path');

    finally
      mFilesystem.free;
    end;

Im not going to divulge to much about this code. Most Smart Pascal developers will understand what’s going on I believe. But in short:

  • mkdir() creates a folder, and returns the folder object
  • mkfile() creates a file and returns the file object
  • FindFileObject() takes a path and recursively drills down to locate the filesystem-object
  • WriteData() stores a variant value in a file
  • ReadData() returns the variant file-content

Since mkDir() and mkFile() returns the object, we can do fancy stuff like chaining make operands together:

mFileSystem.mkDir('first')
        .mkDir('second')
        .mkFile('text.txt',null);

But what about speed I hear you say? Well I had to re-code this twice, because like my friend Eric Grange pointed out the other day – JSON.Stringify() is extremely costly in terms of CPU and time. Which means that if every file object supports ISerializable it would take ages before the procedure returns (and then the browser drops the call).

So what I do now is that – when you call SaveTo() to store the full content of the filesystem, it generates a multi-layered array of records. It then calls JSON.Stringify and Deserialize the whole array in a single pass, which is blistering fast.

Note: Localstorage has a limit of some 15 megabytes or so (or was that 10?) so dont expect much. But if you want to store some data, perhaps a document or preferences, then qtx.storage.filesystem is exactly what you need.

Storage galore

Let’s see what happens when we generate 1000 files with a short string as the content. We use TW3LocalStorage as the target medium. Here is a snapshot from Webkit that verifies that it’s been properly stored:

A filesystem on top of LocalStorage

A filesystem on top of LocalStorage

And here is the code which generates the folders and files (pretty neat stuff!):

  w3Button1.OnClick:=Procedure (sender:TObject)
  var
    x:  Integer;
    mName:  String;
    mFileSystem:  TQTXFileSystem;
    mStore: TW3LocalStorage;
  begin

    mFileSystem:=TQTXFileSystem.Create(NIL);
    try
      mFileSystem.mkDir('first')
        .mkDir('second')
        .mkFile('text.txt',null);

      for x:=1 to 1000 do
      begin
        mName:="file" + getNewID().toString() + ".txt";
        mFileSystem.mkfile(mName,"this is fantastic");
      end;

      mStore:=TW3LocalStorage.Create;
      try
        mStore.Open("filesystem");
        try
          mFileSystem.SaveTo("files",mStore);
        finally
          mStore.Close;
        end;
      finally
        mStore.free;
      end;

      showmessage("Data stored!");

    finally
      mFilesystem.free;
    end;
  end;