I'm trying to have a binary file which contains several binary records defined in some struct. However, I do cannot seem to find how to do it. Looking at other examples, I've managed to write strings without problems, but not struct. I just want to write it like I would in C with fwrite(3), but in D version 2.
Here is what I've tried so far:
using stream.write(tr) - writes human readable/debug representation
using stream.rawWrite(tr) - this sounded like what I need, but fails to compile with:
Error: template std.stdio.File.rawWrite cannot deduce function from
argument types !()(TitleRecord), candidates are:
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132): std.stdio.File.rawWrite(T)(in T[] buffer)
trying rawWrite as above, but casting data to various things, also never compiles.
even trying to get back to C with fwrite, but can't get deep enough to get file descriptor I need.
Reading the docs has not been very helpful (writing strings works for me too, but not writing struct). I'm sure there must be simple way to do it, but I'm not able to find it.... Other SO questions did not help me. I D 1.0, it might have been accomplished with stream.writeExact(&tr, tr.sizeof) but that is no longer an option.
import std.stdio;
struct TitleRecord {
short id;
char[49] text;
};
TitleRecord tr;
void main()
{
auto stream = File("filename.dat","wb+");
tr.id = 1234;
tr.text = "hello world";
writeln(tr);
//stream.write(tr);
//stream.rawWrite(tr);
//stream.rawWrite(cast(ubyte[52]) tr);
//stream.rawWrite(cast(ubyte[]) tr);
//fwrite(&tr, 4, 1, stream);
}
For this that error is saying it expects an array not a struct. So one easy way to do it is to simply slice a pointer and give that to rawWrite:
stream.rawWrite((&tr)[0 .. 1]);
The (&tr) gets the address, thus converting your struct to a pointer. Then the [0 .. 1] means get a slice of it from the beginning, grabbing just one element.
Thus you now have a T[] that rawWrite can handle containing your one element.
Be warned if you use the #safe annotation this will not pass, you'd have to mark it #trusted. Also of course any references inside your struct (including string) will be written as binary pointers instead of data as you surely know from C experience. But in the case you showed there you're fine.
edit: BTW you could also just use fwrite if you like, copy/pasting the same code over from C (except it is foo.sizeof instead of sizeof foo). The D File thing is just a small wrapper around C's FILE* and you can get the original FILE* back out to pass to the other functions with stream.getFP() http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )
rawWrite expects an array, but there are many workarounds.
One is to create a single element array.
file.rawWrite([myStruct]);
Another one is casting the struct into an array. My library called bitleveld has a function for that called reinterpretAsArray. This also makes it easy to create checksums of said structs.
Once in a while I've encountered issues with alignment using this method, so be careful. Could be fixed by changing the align property of the struct.
Related
When I have an Arguments instance, is it possible to read the parts that make it up?
It seems like the only thing I can do with it is pass it to format! and friends.
So in the example below, is it possible to read "{} hello {}", 1 and 2?
The reason I ask is that I want to implement a custom fern log format, and I want to determine if any of the strings are valid JSON so that they can go into a separate meta JSON key for JSON-lines logging. This way the JSON data does not need to parsed by the end user from the message.
https://doc.rust-lang.org/std/fmt/struct.Arguments.html
let x: Arguments = format_args!("{} hello {}", 1, 2);
// Can I read back the parts from `x`?
No, Arguments does not expose its internals in a way that can be inspected.
And even if you could access the internals (as seen in the source), the elements are stored in a type-erased form, making it difficult to use beyond running it through its associated formatting function.
I'm writing a class named "MyObject".
one of the class methods is:
addTo: aCodeString assertType: aTypeCollection
when the method is called with aCodeString, I want to add (in runtime) a new method to "MyObject" class which aCodeString is it's source code and inject type checking code into the source code.
for example, if I call addTo: assertType: like that:
a := MyObject new.
a addTo: 'foo: a boo:b baz: c
^(a*b+c)'
assertType: #(SmallInteger SmallInteger SmallInteger).
I expect that I could write later:
answer := (a foo: 2 boo: 5 baz: 10).
and get 20 in answer.
and if I write:
a foo: 'someString' boo: 5 baz: 10.
I get the proper message because 'someString' is not a SmallInteger.
I know how to write the type checking code, and I know that to add the method to the class in runtime I can use 'compile' method from Behavior class.
the problem is that I want to add the type checking code inside the source code.
I'm not really familiar with all of squeak classes so I'm not sure if I rather edit the aCodeString as a string inside addTo: assertType: and then use compile: (and I don't know how to do so), or that there is a way to inject code to an existing method in Behavior class or other squeak class.
so basically, what I'm asking is how can I inject string into an existing string or to inject code into an existing method.
There are many ways you could achieve such type checking...
The one you propose is to modify the source code (a String) so as to insert additional pre-condition type checks.
The key point with this approach is that you will have to insert the type checking at the right place. That means somehow parsing the original source (or at least the selector and arguments) so as to find its exact span (and the argument names).
See method initPattern:return: in Parser and its senders. You will find quite low level (not most beautiful) code that feed the block (passed thru return: keyword) with sap an Array of 3 objects: the method selector, the method arguments and the method precedence (a code telling if the method is connected to unary, binary or keyword message). From there, you'll get enough material for achieving source code manipulation (insert a string into another with copyReplace:from:to:with:).
Do not hesitate to write small snippets of code and execute in the Debugger (select code to debug, then use debug it menu or ALT+Shift+D). Also use the inspectors extensively to gain more insight on how things work!
Another solution is to parse the whole Abstract Syntax Tree (AST) of the source code, and manipulate that AST to insert the type checks. Normally, the Parser builds the AST, so observe how it works. From the modified AST, you can then generate new CompiledMethod (the bytecode instructions) and install it in methodDictionary - see the source code of compile: and follow the message sent until you discover generateMethodFromNode:trailer:. This is a bit more involved, and has a bad side effect that the source code is now not in phase with generated code, which might become a problem once you want to debug the method (fortunately, Squeak can used decompiled code in place of source code!).
Last, you can also arrange to have an alternate compiler and parser for some of your classes (see compilerClass and/or parserClass). The alternate TypeHintParser would accept modified syntax with the type hints in source code (once upon a time, it was implemented with type hints following the args inside angle brackets foo: x <Integer> bar: y <Number>). And the alternate TypeHintCompiler would arrange to compile preconditions automatically given those type hints. Since you will then be very advanced in Squeak, you will also create special mapping between source code index and bytecodes so as to have sane debugger and even special Decompiler class that could recognize the precondition type checks and transform them back to type hints just in case.
My advice would be to start with the first approach that you are proposing.
EDIT
I forgot to say, there is yet another way, but it is currently available in Pharo rather than Squeak: Pharo compiler (named OpalCompiler) does reify the bytecode instructions as objects (class names beginning with IR) in the generation phase. So it is also possible to directly manipulate the bytecode instructions by proper hacking at this stage... I'm pretty sure that we can find examples of usage. Probably the most advanced technic.
Using the map file I can find the address of any variable of my C software. I would like to have access to structure element addresses also, not only to the address to the struct.
Is there an easy way of getting this without needing to parse the whole code and look for the struct definitions or manually adding the offset to the struct variable? I can't seem to find anything helpful in the .map file alone but perhaps other compiler output files could have more information.
Is there any way to duplicate a ParserRule? I need a real deep copy, so copyFrom() doesn't do the trick. Or must I re-parse the code?
An alternative idea how to solve the following would also be much appreciated:
I am working on a compiler, translating old legacy code to modern programming languages, in this case EGL -> Java.
EGL has a concept called Standalone Function, which are similar to C-macros. This means that code inside the functions can reference symbols in the calling scope. So both defining and resolving of symbols and type promotion are context-dependent.
In ANTLR3, we solved this by dupTree(), and simply made a copy to work on in each calling scope.
Dynamic types is not an option.
Example (pseudo code) to illustrate:
Program A
int var = 4;
saf(); # Prints 5
end A;
Program B
String var = "abc";
saf(); # Prints abc1
end B;
function saf()
int j = 1;
print(var + j);
end saf;
As of version 4.2, ANTLR 4 does not include any API for manipulating the structure of a parse tree after the parse is complete. This is an area we are currently exploring, especially considering the possibilities created by the new pattern matching syntax.
For duplicating trees, I recommend you implement the visitor interface created when you generated your parser. This will allow you to call visit on any node in your parse tree to create a deep copy of that node.
I have added the CString value in CPtrList. And using Find function. When I try to Find the CString value using Find method of CPtrList, I always got NULL position.
Below is my code to add the CString value in CPtrList ptrFolderPath:
CString sTemp;//
ptrFolderPath.AddTail(new CString (sTemp));
While searching I using below code:
POSITION pos = ptrFolderPath.Find(sPath.GetBuffer(sPath.GetLength()));
here sPath is a CString.
But the pos value is always NULL.
Any idea, where I am missing?
The key point is a line in the MSDN Help for CPtrList::Find(): "Note that the pointer values are compared, not the contents of the objects."
When your code calls "new CString (sTemp)" a new CString object is created, and what is returned (and added to the CPtrList) is the pointer value - the location in memory of your new CString. Let's say, for example, this is at memory location 0x001234500.
Your code that calls Find() is passing in the address of character buffer, but, even if this contains the same string characters as your above CString, its location in memory will be completely different. Since you're not passing in 0x0012234500 (in this example), you don't find the entry you expect.
Given what you appear to be trying to do, CPtrList is probably not the appropriate container type - something like CStringList would be more suitable, since there comparisons are done by value (i.e. the contents of the string) not by pointer.
If all this doesn't make sense, I'm afraid that you need to spend some time reading up on pointers, and concepts such as the difference between equality (two different objects that have the same value) and identity (different references to the same object)