Pascal : write a very long string without reference-counted types (ex:ansistring) - freepascal

I'm making a unit library in pascal at the moment. I would like to know whether I could assign a very long string without using Ansistring or {$H+}, because I couldn't assign typed files with reference-counted types. Thanks before.
EDIT : Code added
type
dataFilm = record
title : array [1..255] of char;
genre : array [1..255] of char;
viewerRating : array [1..255] of char;
duration : integer;
synopsis : array [1..2000] of char;
priceWeekdays : longint;
priceWeekend : longint;
end;
theatreUDT = record
mainDataFilm : array [0..100] of dataFilm;
end;
ftheatreUDT = record
fmainDataFilm : file of dataFilm; //It fails here when i use ansistring
end;
procedure loadMain(var main : theatreUDT; var fmain:ftheatreUDT);
begin
assign(fmain.fmainDataFilm,'Data/dataFilm.dat');
reset(fmain.fmainDataFilm);
end;
The program has no problem at all, only, it can't hold a very long string for synopsis.

You can use array of char to have longer strings.
dataFilm = record
title : string;
genre : string;
viewerRating : string;
duration : integer;
synopsis : array[0..1999] of char;
priceWeekdays : longint;
priceWeekend : longint;
end;
However, note that this is not a very good solution because
a) it means that you have to choose a maximum length for the string. If you choose the length too small, some texts will not fit. If you choose the length too big, you waste lots of disk space because the space a record in the file takes is always the same based on the definition of the record.
b) you cannot easily modify the structure of the data. For example, if you want to add a "director" field to the information about the movie, you cannot do so without writing code to convert the old file format to the new file format. Basically you cannot change the definition of the dataFilm type once you have created files with this code.
c) You cannot easily look into the files any other way. If you use some standard like JSON or XML or even a database, you can easily look at the content with other tools.
d) you cannot access the files with other programming environments as easily. You might want to migrate from Pascal to some other environment in the future or allow other tools to access the files. This is easier using some standard format or a database than when using the pascal way.

Related

ulkJson usage in Delphi 6

lets says i have a code like this,
json:= TlkJSON.ParseText(Memo1.Text);
if Assigned(json) then
begin
json:= json.Field['journals'];
if Assigned(json) then
begin
json:= json.Field['journal_details'];
if Assigned(json) then
begin
Memo2.Lines.Add(VarToStr(json.Child[0].Value));
end;
end;
end;
it's used for tracing my json object had field "journals" and "journal_details" in it.
I want to make it more dynamic so it can detect if the value in json object was array/list/custom list and it contain all the detail error message i want to re - translate again so the user can understand the message.
Any clue will be appreciated.
as #MyICQ suggestion, this is snippet of data that i want to re - translate look like.
[{"code":"H003","validations":["phone_invalid_format"]},{"code":"H004","validations":["phone_invalid_format"]},{"code":"H005","validations":["phone_invalid_format"]},{"code":"H006","validations":["phone_invalid_format"]},{"code":"H010","validations":["phone_invalid_format"]}]
with note, the string was not always with the same structure.
this is the output, i wish to have at least
Error List Data :
> H003 : Note = Phone_invalid_format
> H004 : Note = Phone_invalid_format
> H005 : Note = Phone_invalid_format
> H006 : Note = Phone_invalid_format
> H010 : Note = Phone_invalid_format
so far all i can get is to detect how many array or object in the string, but failed in retrieve the value in it.
There is a function in lkJSON to find the type of element. This is called SelfType, enumeration of TlkJSONtypes: (jsBase, jsNumber, jsString, jsBoolean, jsNull, jsList, jsObject).
You can write this out using SelfTypeName where you get the same as enum, only as a string.
So basically something along:
begin
js := TlkJSON.ParseText(txt);
writeln(js.SelfTypeName); // get the type as a string
if js.SelfType in [jsList] then
begin
// process as list
end
else
if js.SelfType in [jsObject] then
begin
// process as object
end
else if js.SelfType not in [jsBase] then
begin
// write the value of number, string, boolean, null
end;
end;
Obviously you can then make a parse_element function which you can call recursively.
lkJSON seems to be still updated, this GitHub project lists 1.09 from 1 Oct 2021.
The documentation is fairly sparse, but it does the job on older Delphi versions where superobject unfortunately won't compile.
If you google keywords like SelfName and lkJSON there are plenty examples online to get you going.

Creating string debug Vec for state machine

When designing a state machine in Verilog I will normally use localparam to define state names. Most simulators will be able to deduce this and during debugging you can view the state signal by name and not by a number. For simulators that don't figure this out automatically (Icarus), I will generally do something like the following:
`ifdef SIMULATION
reg [8*40:1] state_name;
always #(*) begin
case(state)
WAIT_SDS : state_name = "WAIT_SDS";
IDLE : state_name = "IDLE";
HEADER_DI : state_name = "HEADER_DI";
HEADER_WC0 : state_name = "HEADER_WC0";
HEADER_WC1 : state_name = "HEADER_WC1";
HEADER_ECC : state_name = "HEADER_ECC";
LONG_DATA : state_name = "LONG_DATA";
CRC0 : state_name = "CRC0";
CRC1 : state_name = "CRC1";
IDL_SYM_ST : state_name = "IDL_SYM_ST";
endcase
end
`endif
Allowing me to plot this signal in ASCII.
I have been trying to find a decent way to perform this in Chisel but I'm having no real luck. I currently use ChiselEnum and while I know there was a issue on the Github for trying to make it print a localparam it's not implemented yet. So I would like to add this to what Chisel generates.
Is there a way to achieve this, or something similar with current Chisel APIs?
One issue is I would need to create something and also put a dontTouch around it. If I can't wrap in SYNTHESIS ifdefs then it would likely create some logic I don't want.
An alternative method would be to automatically generate translation files for the waveform viewer.
Here's a FIRRTL transform targeting gtkwave. It creates translation filter files for all ChiselEnums definitions and a "gtkw" savefile populated with all ports and submodules.
https://gist.github.com/kammoh/b3c85db9f2646a664f8dc84825f1bd1d
You can use it with chiseltest (chisel-testers2) like this:
class MySpec extends FlatSpec with ChiselScalatestTester{
val annos = Seq(
WriteVcdAnnotation,
GtkwaveColoredFiltersAnnotation,
)
test(new MyModule).withAnnotations(annos) { dut =>
// test logic
}
}
It's still a work in progress and if there's interest, I can suggest a PR for adding it to chiseltest.

LUA, multiple number string to number

so I use web to request json:
{"number":"1,2,3"} OR table = {number="1,2,3"}
and when I used this, it shows number:
typeof(1,2,3)
but when i directly get the data from the json/table, it shows string, so is there anyway to convert it to show it as number?
A Lua pattern might also a good choice to get the numbers from the raw string; then use tonumber() as suggested and add the numbers to a table in the sample code as shown below:
numbers = {}
str = '1,2,3'
for num in string.gmatch(str, '([^,]+)') do
table.insert(numbers, tonumber(num))
end

In Ada, How do I recursively map and memory manage a type within itself

I've been struggling with this little issue for a while. I am trying to create my own implementation of an internal JSON structure. The challenge is that with Ada I have to use an access type to make it recursive and access types have the risk of leaking if I don't have it tightly controlled. In order to make it controlled, I kept all the real activity private I provided Get (Source:...) and Set (Target:...; Value:...) functions/procedures for the Node type that will attempt to verify and handle any existing Vector (json-array) or Map (json-object) elements. In order to further ensure that I was using stable features of Ada 2012 and catching contents as they go out of scope, I tried to use a Protected_Controlled type and "managing" Ada libraries, but found that the container libraries couldn't handle protected types, so I used simply Controlled. The Finalize (...) procedure is for any Vector or Map types and recursively frees the Node_Value.Reference.
My question is if I am applying Ada 2012 correctly, or else how do I create a memory managed recursion of a type that could be either a vector/map or a string/number?
private
...
type Node_Access is access Node;
type Node_Value is new Ada.Finalization.Controlled with record
Reference : Node_Access;
end record;
overriding procedure Initialize (Item : in out Node_Value);
overriding procedure Adjust (Item : in out Node_Value);
overriding procedure Finalize (Item : in out Node_Value);
...
package Of_Array is new Ada.Containers.Indefinite_Vectors (Natural, Node_Value);
package Of_Object is new Ada.Containers.Indefinite_Ordered_Maps (Wide_String, Node_Value);
type Node is record
...
Vector : aliased Of_Array.Vector;
Object : aliased Of_Object.Map;
end record
with Size => 96;
procedure Free is new Ada.Unchecked_Deallocation (Node, Node_Access);
The way to do it (in my opinion) is to use OOP and have an abstract element as the root node of a family of types representing the different kinds of data which can be stored.
An array of elements can then be implemented as a vector of the class rooted at the abstract element type. An "object" can be implemented as a hash-table with a string key and the class rooted at the abstract element type as the values.
Self-referential types without access types are a valid use for type extension in combination with an indefinite container. A simple example is S-expressions, or Sexes. A Sex is either an atom or a list of zero or more Sexes. The right way to be able to do this would be
with Ada.Containers.Indefinite_Vectors;
package Sexes is
type Sex is private;
-- Operations on Sex
private -- Sexes
package Sex_List is new Ada.Containers.Indefinite_Vectors
(Index_Type => Positive, Element_Type => Sex); -- Illegal
type Sex (Is_Atom : Boolean := False) is record
case Is_Atom is
when False =>
Value : Atom;
when True =>
List : Sex_List.Vector;
end case;
end record;
end Sexes;
but Ada doesn't allow this. We can use type extension to get around this:
private -- Sexes
type Root is tagged null record;
package Sex_List is new Ada.Containers.Indefinite_Vectors
(Index_Type => Positive, Element_Type => Root'Class);
type Sex (Is_Atom : Boolean := False) is new Root with record
case Is_Atom is
when False =>
Value : Atom;
when True =>
List : Sex_List.Vector;
end case;
end record;
end Sexes;
which is legal. The only catch is that you have to convert anything taken from List to Sex (or Node in your case).
HTH; sorry about the late response.

In Delphi using MyDAC, how do I write an entire record as a string?

As the title suggests, using Delphi 2010 and MyDAC 7.1, how do I output an entire string as a string like JSON / XML / CSV or some other plain text option?
eg output:
{user_id:1;username:testuser;password:testpass}
Presuming that MyDAC is a standard TDataSet descendant, you can build the string manually. For instance, for JSON:
var
i: Integer;
Output: string;
begin
Output := '{'; // #123;
for i := 0 to MyQry.FieldCount - 1 do
Output := Output +
MyQry.Fields[i].FieldName + ':' + // #58
MyQry.Fields[i].AsString + ';'; // #59
// Replace final ; with closing } instead
Output[Length(Output)] := '}'; // #125
end;
Or you can Google to find a Delphi JSON library (like SuperObject) and use it instead, as is done here.
For XML, use the same type loop with TXMLDocument. You can search for previous posts here tagged with Delphi to find examples.
For CSV, it can get complicated based on your data and the requirements. For instance, do you want or need a header row with field names? Does your data contain data that contains spaces or punctuation or CR/LFs? The easiest solution is to search for an already-existing library (via Google or Bing, not here) that exports to CSV.
According to the documentation you can use the SaveToXML procedures. should be something like this:
var
MyQuery: TMyQuery;
begin
try
MyQuery := TMyQuery.Create();
MyQuery.Connection := AConnection;
MyQuery.SQL.Text := ACommand;
MyQuery.Execute();
MyQuery.SaveToXML(<tstream or file>)
except
raise;
end;
end;