c: Convert ipv6 address to string at compile time - c

This is a longshot, but I'm wondering if there are any tricks to convert a constant ipv6 address string into two 64 bit integers at compile time. (this is on an embedded system, and thus runtime and memory are both valuable commodities). Ideally the code would look something like:
const uint64_t addr[2] = { IPV6_TO_UINT64S("::ffff:192.168.1.1") };
which would produce:
const uint64_t addr[2] = { 0x0000000000000000ULL, 0x0000ffffc0a80101ULL };

For this sort of thing I'd recommend writing a template header file (not C++ templates, but fill-in-the-blank templates), putting the human-readable values in a config file, and using a small program to fill in the blanks.
For example, the config file might be in JSON. (This is obviously overkill for a single value, I'm just showing the technique.)
{
"addr": "::ffff:192.168.1.1"
}
You could use an existing template language, or make up your own. For something as simple as a C header file, you can get away with something very simple.
const uint64_t addr[2] = { %%addr%% };
And the code to read the config and process the template simple in a ubiquitous scripting language like Ruby.
#!/usr/bin/env ruby
require 'json'
template, config_file = ARGV[0..1]
# Load the config file
config = JSON.load( File.new(config_file) )
# Ensure missing config variables throw an error
config.default_proc = proc do |hash, key|
throw "Config key '#{key}' is missing from #{config_file}"
end
# ...do whatever processing on the config variables you want...
# Fill in the template.
IO.foreach(template) { |line|
puts line.gsub(/%%(.*?)%%/) { config[$1] }
}
I employ this technique in the y2038 library. It has to probe the system to determine the limits of time.h, then encode those limits into a custom header file. munge_config reads the configuration values (from the build system, not from a JSON config, but the result is the same: a hash), and fills in the template. This is the time64_limits.h.in template and an example of a resulting time64_limits.h header file.

Related

Is there a file object to get path or name of a file in Nim?

Let's say, I would like to use a single object to represent a file and I'd like to get the filename (or path) of it so that I can use the name to remove the file or for other standard library procedures. I'd like to have a single abstraction which can be used with all available file-related standard library procedures.
I've found FileInfo but in my research I didn't find a get-file-name-procedure. File and FileHandle are pretty useless from a software engineering point of view because they provide no convenient abstraction and don't have members.
Is there a file abstraction (object) in Nim, which provides fast access to FileInfo as well as the file name so that a file doesn't need more than one procedure parameter?
There is no such abstraction in Nim, or any other language, simply because you are asking for an impossible thing to do with most filesystems. Consider the FileInfo structure and its linkCount field which tells you the number of hard links the file object has. But there is no way to get-a-filename from one or all of those links short of building and updating yourself a database of the whole filesystem.
While most filesystems allow access to files through paths, there is rarely a filesystem that gives paths from files because they actually don't need one! An example would be a Unix filesystem where one process opens a file through a path, then removes the path without closing the file. While the process holding the file open is alive, that file won't actually disappear, so you would have the case of a file without path.
The issue of handling paths, especially considering cross platform applications, involves its own can of worms: if you store paths as strings, what is the path separator and how do you escape it? Does your filesystem support volumes that require special case handling? What string encoding do paths use to satisfy all users? Just the encoding issue requires tons of tables and conversions which would bog down every other API wishing to get just a file like handle to read or write bytes.
A FileInfo is just a snapshot of the state of the file at a given time, a file handle is the live file object you can operate on, and a path (or many paths if your filesystem supports hard links) is just a convenience name for end users.
These are all very different things, which is why they are separate. Your app may need a more complex abstraction than other programmers are willing to tolerate, so create own abstraction which holds together all the individual pieces you need. For instance, consider the following structure:
import os
type
AppFileInfo = object
fileInfo: FileInfo
file: File
oneOfMany: string
proc changeFileExt(appFileInfo: AppFileInfo, ext: string): string =
changeFileExt(appFileInfo.oneOfMany, ext)
proc readAll(appFileInfo: AppFileInfo): string =
readAll(appFileInfo.file)
Those procs simply mimic the respective standard library APIs but use your more complex structure as inputs and transform it as needed. If you are worried about this abstraction not being optimised due to the extra proc call you could use a template instead.
If you follow this route, however, at some point you will have to ask yourself what is the lifetime of an AppFileInfo object: do you create it with a path? Do you create it from a file handle? Is it safe to access the file field in parts of your code or has it not been initialised properly? Do you return errors or throw exceptions when something goes wrong? Maybe when you start to ask yourself these questions you'll realise they are very app specific and are very difficult to generalise for every use case. Therefore such a complex object doesn't make much sense in the language standard library.
I created the missing solution myself. I basically extended the File type using a global encapsulated table. Extending Types like this could be a useful idiom in Nim because of UFCS.
import tables
type FileObject = object
file : File
mode : FileMode
path : string
proc initFileObject(name: string; mode: FileMode; bufsize = -1) : FileObject =
result.file = open(name, mode, bufsize)
result.path = name
result.mode = mode
var g_fileObjects = initTable[File, FileObject]()
template get(this: File) : var FileObject = g_fileObjects[this]
proc openFile*(filepath: string; mode: FileMode = fmRead; bufsize = -1) : File =
var fileObject = initFileObject(filepath, mode, bufsize)
result = fileObject.file
g_fileObjects[result] = fileObject
proc filePath*(this: File) : string {.raises: KeyError.} =
return this.get.path
proc fileMode*(this: File) : FileMode {.raises: KeyError.} =
return this.get.mode
from os import tryRemoveFile
proc closeOrDeleteFile[delete = false](this: File) : bool =
result = g_fileObjects.hasKey(this)
if result:
when delete:
result = this.filepath.tryRemoveFile()
g_fileObjects.del(this)
this.close()
proc closeFile*(this: File) : bool = this.closeOrDeleteFile[:false]
proc deleteFile*(this: File) : bool = this.closeOrDeleteFile[:true]
Now you can write
var f = openFile("myFile.txt", fmWrite)
var g = openFile("hello.txt", fmWrite)
echo f.filePath
echo f.deleteFile()
g.writeLine(g.filePath)
echo g.closeFile()

How to read a text file from resources without javaClass

I need to read a text file with readLines() and I've already found this question, but the code in the answers always uses some variation of javaClass; it seems to work only inside a class, while I'm using just a simple Kotlin file with no declared classes. Writing it like this is correct syntax-wise but it looks really ugly and it always returns null, so it must be wrong:
val lines = object {}.javaClass.getResource("file.txt")?.toURI()?.toPath()?.readLines()
Of course I could just specify the raw path like this, but I wonder if there's a better way:
val lines = File("src/main/resources/file.txt").readLines()
Thanks to this answer for providing the correct way to read the file. Currently, reading files from resources without using javaClass or similar constructs doesn't seem to be possible.
// use this if you're inside a class
val lines = this::class.java.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
// use this otherwise
val lines = object {}.javaClass.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
According to other similar questions I've found, the second way might also work within a lambda but I haven't tested it. Notice the need for the ?. operator and the lines?.let {} syntax needed from this point onward, because getResourceAsStream() returns null if no resource is found with the given name.
Kotlin doesn't have its own means of getting a resource, so you have to use Java's method Class.getResource. You should not assume that the resource is a file (i.e. don't use toPath) as it could well be an entry in a jar, and not a file on the file system. To read a resource, it is easier to get the resource as an InputStream and then read lines from it:
val lines = this::class.java.getResourceAsStream("file.txt").bufferedReader().readLines()
I'm not sure if my response attempts to answer your exact question, but perhaps you could do something like this:
I'm guessing in the final use case, the file names would be dynamic - Not statically declared. In which case, if you have access to or know the path to the folder, you could do something like this:
// Create an extension function on the String class to retrieve a list of
// files available within a folder. Though I have not added a check here
// to validate this, a condition can be added to assert if the extension
// called is executed on a folder or not
fun String.getFilesInFolder(): Array<out File>? = with(File(this)) { return listFiles() }
// Call the extension function on the String folder path wherever required
fun retrieveFiles(): Array<out File>? = [PATH TO FOLDER].getFilesInFolder()
Once you have a reference to the List<out File> object, you could do something like this:
// Create an extension function to read
fun File.retrieveContent() = readLines()
// You can can further expand this use case to conditionally return
// readLines() or entire file data using a buffered reader or convert file
// content to a Data class through GSON/whatever.
// You can use Generic Constraints
// Refer this article for possibilities
// https://kotlinlang.org/docs/generics.html#generic-constraints
// Then simply call this extension function after retrieving files in the folder.
listOfFiles?.forEach { singleFile -> println(singleFile.retrieveContent()) }
In order to have the same url that work for both Jar or in local, the url (or path) needs to be a relative path from the repository root.
..meaning, the location of your file or folder from your src folder.
could be "/main/resources/your-folder/" or "/client/notes/somefile.md"
The url must be a relative path from the repository root.
it must be "src/main/resources/your-folder/" or "src/client/notes/somefile.md"
Now you get the drill, and luckily for Intellij Idea users, you can get the correct path with a right-click on the folder or file -> copy Path/Reference.. -> Path From Repository Root (this is it)
Last, paste it and do your thing.

Setting file path in imported C function inside Swift Framework

I am trying to use C library source files inside my Cocoa Framework which has function named
void swe_set_ephe_path(char *path);
Which will basically be
swe_set_ephe_path(”C:\\SWEPH\\EPHE”);
for windows.
This library contains other data files which only work after this function is set.
When imported to Swift the function looks like this
swe_set_ephe_path(path: UnsafeMutablePointer<Int8!>)
Since i want to bundle up all the data files in framework and use it in my application, i have done something like this
public class SwissEphemeris {
public init() {
let path = Bundle.main.bundlePath
let swePath = UnsafeMutablePointer<Int8>(mutating: (path as NSString).utf8String)
swe_set_ephe_path(swePath)
}
}
But it seems it's not working and the functions which needs data to be searched in files are not able to operate.
If anybody interested to look into Swiss library documentation, check here for the link,
https://www.astro.com/swisseph/swephprg.htm#_Toc505244836
There are two problems:
First, the resource files are in the “Resources” subdirectory of the framework, not in the top-level framework directory. You can obtain a path to that directory with
let resourcePath = Bundle(identifier: "com.Abhi.SwissFramework")!.resourcePath!
or with
let resourcePath = Bundle(for: type(of: self)).resourcePath!
I suggest to force-unwrap the optionals because you know that the bundle and the resources directory exist. A failure would indicate a build problem which should be detected early.
Second, the C function takes a char * argument even though it does not mutate the passed string. Here you can use the approach from UnsafeMutablePointer<Int8> from String in Swift:
resourcePath.withCString {
swe_set_ephe_path(UnsafeMutablePointer(mutating: $0))
}
Even better: use the dedicated method withUnsafeFileSystemRepresentation() to get the file system representation of the resource path as a C string:
let resourceURL = Bundle(for: type(of: self)).resourceURL!
resourceURL.withUnsafeFileSystemRepresentation {
swe_set_ephe_path(UnsafeMutablePointer(mutating: $0))
}

How to read config files on elixir mix project

I am creating an elixir project to search for patterns in files.
I want to store those patterns a config files to allow for easy changes in the app.
My first idea is storing those files as exs files in the config folder in the mix project.
So, the questions are:
Is there any easy way to store the config in the files a a keyword list?
How would I load it in the app?
I see there are modules like File to read the file, but is there no standard way to parse keyword lists in elixir? I was thinking something similar as the yml files in Rails.
You can read keyword lists stored in a *.exs file, using Mix.Config.read(path). For writing Elixir terms to a *.exs file, you can use Inspect.Algebra.to_doc(%Inspect.Opts{pretty: true}) and write the resulting string content to a file using File.write. It's not as well formatted as if you did it by hand, but it's definitely still readable.
If you don't mind using Erlang terms, you can read and write those easily using :file.consult(path) and :file.write_file(:io_lib.fwrite('~p.\n', [config]), path) respectively.
Using Code.eval_file
Adding another option, is to evaluate the file as a code file, using Code.eval_file and get in return the result as an elixir construct.
Config file config1.ex:
%{configKey1: "configValue1", configKey2: "configValue2"}
Reading the file:
{content, _} = Code.eval_file("config1.ex")
*evaluating a code file has security consideration needs to take in mind.
Regarding using Mix.Config.read! in #bitwalker correct answer
the config file needs to be in a specific format of:
[
appName: [key1: "val1", key2: "val2"]
]
In the Mix.Config.read code, it try to validate the contents and expect a main keyword list [ {}, {}.. ] which includes keys that has value of type keyword list also.
The code is not long:
def validate!(config) do
if is_list(config) do
Enum.all?(config, fn
{app, value} when is_atom(app) ->
if Keyword.keyword?(value) do
true
else
raise ArgumentError,
"expected config for app #{inspect app} to return keyword list, got: #{inspect value}"
end
_ ->
false
end)
else
raise ArgumentError,
"expected config file to return keyword list, got: #{inspect config}"
end
end
We can circumvent and use a first key which is not atom, and then the validate stops but does not throw:
[
{"mockFirstKey", "mockValue"},
myKey1: "myValue1",
myKey2: "myValue2"
]

Hash-based logger for embedded application

Currently I am sending the UART the strings I want to log and reading it on the host with any terminal.
In order to reduce the logging time and hopefully the image size as well (my flash is tiny), I figured out that the strings are unused in the embedded system, so why storing them on the flash?
I want to implement a server, whom I can send a hashed-key of any string (for example - it's ROM address) and the string will be output to file or screen.
My questions are:
How to create the key2string converter out of the image file (the OS is CMX, but can be answered generally)
Is there a recomended way to generate image, that will know the strings addresses but will exclude them from ROM?
Is there a known generic (open-source or other) that implemented a similar logger?
Thanks
Rather than holding hard-coded strings, then trying to hash the answers and sent it via a UART, then somehow remove the strings from the resulting image, I suggest the following.
Just send an index for an error code. The PC side can look up that index and determine what the string is for that condition. If you want the device code to be more clear, the index can be an enumeration.
For example:
enum errorStrings
{
ES_valueOutOfLimits = 1,
ES_wowItsGettingWarm = 2,
ES_randomError = 3,
ES_passwordFailure = 4
};
So, if you were sending data to the UART via printf, you could do the following:
printf("%d\n",(int)ES_wowItsGettingWarm);
Then your PC software just needs to decode the "2" that comes across the UART back into a useful string of "Wow it's getting warm."
This keeps the firmware small, but you need to manually keep the file containing the enum and the file with the strings in sync.
My solution is sending file name and line (which should be 14-20 Byte) and having a source parser on the server side, which will generate map of the actual texts. This way the actual code will contain no "format" strings, but single "filename" string for each file. Furthermore, file names can be easily replaced with enum (unlike replacing every string in the code) to reduce the COMM throughput.
I hope the sample psaudo-code will help clarifying the idea:
/* target code */
#define PRINT(format,...) send(__FILE__,__LINE__,__VA_ARGS__)
...
/* host code (c++) */
void PrintComm(istream& in)
{
string fileName;
int line,nParams;
int* params;
in>>fileName>>line>>nParams;
if (nParams>0)
{
params = new int[nParams];
for (int i=0; i<nParams; ++i)
in>>params[i];
}
const char* format = FindFormat(fileName,line);
...
delete[] params;
}

Resources