Swift 2 and Linux/OS X differences - linux

I'm trying to port some basic app from OS X to Linux but it seems that even basic stuff is missing on Linux platform. Is there some documentation what is missing ??
Here is example:
exmcast.swift:7:20: error: value of type 'String' has no member 'stringByReplacingOccurrencesOfString'
let name: String = address.stringByReplacingOccurrencesOfString(".", withString: "_")
This simple code works on OS X. On Linux - you see results.
It's very hard to port anything when there is no basic info what is missing.
And it looks like even basic stuff is missing..

Swift 3 will be released in fall 2016.
The recently open-sourced Swift and the Linux port are work in progress:
The port is still a work in progress but we’re happy to say that it is usable today for experimentation.
You can go to Swift.org and github.com/apple and enjoy the fantastic work.
When you find something not yet implemented, you can file a bug and/or help implement the feature.
New versions of the open source Swift will be posted regularly on Swift.org.

The method you are trying to call is actually part of NSString. String is bridged behind the scenes to NSString and that is why you are able to use that method on OS X. NSString is part of the Foundation framework, and Foundation is not totally implemented for Linux. You can check the status of the various parts of Foundation here: Foundation Status. NSString is currently only partially implemented.

On OSX you still need to import Foundation
You are free to use pure Swift solution, in your case
let str = "alfa.beta"
// (1)
let str1 = str.characters.map {
$0 == "." ? "_": $0
}.reduce("") { (str, c) -> String in
str + String(c)
}
// (2)
let str2 = String(str.characters.split(".").joinWithSeparator(["_"]))
print(str,str1,str2) // alfa.beta alfa_beta alfa_beta
for something more advanced, you have powerful functions
mutating func replaceRange<C : CollectionType where C.Generator.Element == Character>(subRange: Range<Index>, with newElements: C)
or
mutating func replaceRange(subRange: Range<Index>, with newElements: String)

Related

c# Trying to call a file, filenotfound exception. Is it the VMWare?

This is a really beginner question, I'm trying to read a file and write a JSON, but I keep getting "filenotfound" exception in visual studio. I'm using VMWARE windows 10, and I'm confused about how to establish the directory using VMWare. Maybe it's more of a lack of understanding the code itself than how it's effected by the VMWare.
Also would like to know cases in which VMware effects a similar situation.
I'm trying to call the folder this way:
const string _data1 = "Data1.txt"; // initilize
string Filename = #"\\vmware-host\Shared Folders\Desktop\JSONproject";
then futher down the program:
using (StreamReader r = new StreamReader(_data1))
{
string line;
while ((line = r.ReadLine()) != null)
{
Data1.Add(line); // add to list
}
}
Console.WriteLine(outputMessage);
break;
I've come upon this problem. You need to move the file into the C: rather than it be on the desktop. The VMware desktop is shared with the mac, which makes it ambiguous for visual studio to call.

HTTP Request in Swift without NSURLRequest

We want to make HTTP(S) requests (GET) to call an API. The Problem is, NSURLRequest is (at the moment) not implemented in the Foundation for Linux (https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSURLRequest.swift).
Are there any other possibilities to create an HTTP request?
There is a nice project called HTTPMiddleware that can be useful, it's just a middleware framework but it works well.
Here's a code example:
import HTTP
import HTTPMiddleware
struct Middleware: HTTPRequestMiddlewareType {
func respond(request: HTTPRequest) -> HTTPRequestMiddlewareResult {
// You can change the request and pass it forward
return .Next(request)
// Or you can respond early and bypass the chain
return .Respond(HTTPResponse(statusCode: 404, reasonPhrase: "Not Found"))
}
}
struct Responder: HTTPResponderType {
func respond(request: HTTPRequest) -> HTTPResponse {
// May or may not be called depending on the middleware
return HTTPResponse(statusCode: 200, reasonPhrase: "OK")
}
}
let request = HTTPRequest(method: .GET, uri: URI(path: "/"))
let chain = Middleware() >>> Responder()
let response = chain.respond(request)
Here is the official page, you can also find a JSON parser in the sources that can be useful for common requests.
The installation requires only the uri_parser.
Consider following solution based on ccurl library:
https://dl.dropboxusercontent.com/u/2504173/CurlSampleApp.tar.gz
I did it on Ubuntu 14.04
Swift 3.0 - latest development version:
https://swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-06-06-a/swift-DEVELOPMENT-SNAPSHOT-2016-06-06-a-ubuntu14.04.tar.gz
Following package and instructions worked fine in general:
https://swiftpkgs.ng.bluemix.net/package/SwiftOnTheServer/CCurl
But in order to fix compilation errors I had to modify sots_curl.h in CCurl package. Following line was added:
#include <stdint.h>
For the app building you need to perform following in the app folder:
swift build
For app running you need to perform following command in the app folder:
.build/debug/app
Hope it helps. Ask questions if any :)
Considering that Swift on Linux is fast-evolving work in progress, the best approach, I think, is to hold off doing any serious development until the situation is more stable. Even if you overcome the obstacle of making HTTP requests, there will likely be other unpleasant surprises due to the technology being immature on Linux.
However, if this is just a matter of curiosity and learning, here are some ideas, even though I haven't tried them myself:
Maybe calling CoreFoundation C APIs directly will work.
Write a C wrapper, that provides the interface you need, using good old C network APIs. This approach would probably require more effort than the others, as you will be re-inventing a lot of wheels.
Write a C wrapper, but wrap a higher-level C library that works with URLs; libcurl comes to mind.
Regardless of which of these approaches you take, you will need to interface with C code. One way to do this is to use system modules, see Importing a Swift module using a C library as a possible starting point.
Since mid-2017 there is IBM's SwiftyRequest library, which works on both Linux and iOS. I've tried it on Linux and seems to work fine.
Making a request looks like this (adapted an example from docs):
import SwiftyRequest
let request = RestRequest(method: .get, url: "http://myApiCall/hello")
request.responseString() { response in
switch response.result {
case .success(let result):
print("Success")
case .failure(let error):
print("Failure")
}
}
If you're using JSON for the responses, it can even construct you an object based on a "schema" you provide (have a look at .responseObject and JSONDecodable in the tests for examples).
Not a full answer, but maybe useful to someone:
I only needed NSData(contentsOfURL: NSURL) so I ended up writing a wrapper for KituraNet that does this with a closure. I just check if there is data and return that.
Because NSURL is far from fully implemented I also decided to pass the url as a String for now.
It's not a replacement for NSURLRequest, just the good old convenience of NSData(contentsOfURL: NSURL)
.Package(url: "https://github.com/IBM-Swift/Kitura-net.git", majorVersion: 0, minor: 15),
import KituraNet
extension NSData {
public static func contents(ofUrl urlString:String, completionHandler:((data:NSData?) -> Void)) {
let request = HTTP.request(urlString) { (response) in
guard let response = response else {
completionHandler(data: nil)
return
}
let responseData = NSMutableData()
do {
try response.readAllData(into: responseData)
completionHandler(data: responseData)
return
} catch {
completionHandler(data: nil)
return
}
}
request.end()
}
}

org.apache.commons.jexl2.JexlArithmetic: bitwiseXor in JEXL sandbox

I'm working in a native JEXL sandbox, so there is no need of
expression e = jexl.createExpression
Actually I am able to get this working:
foo = new ("org.apache.commons.jexl2.JexlArithmetic", false);
tmp = foo.multiply("123","123");
with those two lines I can access the var tmp.
Now I want to make a XOR operation like this:
tmp2 = foo.bitwiseXor("3","5");
This results in an error message as following:
org.apache.commons.jexl2.JexlException: unknown or ambiguous method
any ideas how to make this working?
found the answer by myself ;)
the method bitwiseXor is available only in JEXL version 2.1 and newer.
the version I am using in my sandbox is 2.0, which was a little bit hard to find out.
cheers

Setting process name (as seen by `ps`) in Go

The following (rightfully) doesn't work:
package main
import (
"os"
"time"
)
func main() {
os.Args[0] = "custom name"
println("sleeping")
time.Sleep(1000 * time.Second)
println("done")
}
Some languages provide this feature of setting process name as a built-in functionality (in Ruby, for instance, it is only a matter of assigning to $0) or as a third-party library (Python).
I'm looking for a solution that works, at least, on Linux.
There are multiple ways to accomplish this, and many of them only work in certain situations. I don't really recommend doing it, as (for one thing) it can result in your process showing up with different names in different situations. They require using syscall and/or unsafe, and so you're deliberately subverting the safety of the Go language. That said, however, your options seem to be:
Modify argv[0]
func SetProcessName(name string) error {
argv0str := (*reflect.StringHeader)(unsafe.Pointer(&os.Args[0]))
argv0 := (*[1 << 30]byte)(unsafe.Pointer(argv0str.Data))[:argv0str.Len]
n := copy(argv0, name)
if n < len(argv0) {
argv0[n] = 0
}
return nil
}
In Go, you don't have access to the actual argv array itself (without calling internal runtime functions), so you are limited to a new name no longer than the length of the current process name.
This seems to mostly work on both Darwin and Linux.
Call PR_SET_NAME
func SetProcessName(name string) error {
bytes := append([]byte(name), 0)
ptr := unsafe.Pointer(&bytes[0])
if _, _, errno := syscall.RawSyscall6(syscall.SYS_PRCTL, syscall.PR_SET_NAME, uintptr(ptr), 0, 0, 0, 0); errno != 0 {
return syscall.Errno(errno)
}
return nil
}
The new name can be at most 16 bytes.
This doesn't work on Darwin, and doesn't seem to do much on Linux, though it succeeds and PR_GET_NAME reports the correct name afterward. This may be something peculiar about my Linux VM, though.
To change a process name on Linux, you need to use the prctl system call combined with the PR_SET_NAME option.
At the moment, I don't think you can do this in Go code. You can, however, build a small C module to do this and then integrate it into your Go build.
I don't think that "process title" is a well defined term. Anyway, what has Ruby to do with Go? The documentation for os.Args doesn't mention any "process title", nor it says any magic will happen on assigning to a slice item. The later is actually a general property of Go. There's no magic getters/setters for struct fields, variables of array/slice items, so a simple assignment simply assigns and does nothing more and cannot do anything more.
In short, the lack of magic is the expected, correct behavior.
For fiddling with process properties other than the portably accessible ones via the 'os' package, one has to use package 'syscall' in a platform specific way. But then the build constraints (discussed here) can help to correctly handle stuff across platforms.

Converting C-style series of casts on AfxGetMainWnd from VC6/MFC6 to operate in modern MFC version (VC++2008 and later)

An application I'm porting from Visual C++ 6.0 to the MFC version in VC++2008, does a lot of get-AfxGetMainWnd()-and-do-C-Style-casts on it like this:
CUserInterfaceDoc *m_pDoc = (CUserInterfaceDoc*)((CFrameWnd *)AfxGetMainWnd())
->GetActiveDocument();
When I try the steps above, simply converting to dynamic_cast<>, I find that the Main Window is no longer accessible via casting-to-a-CUserInterfaceDoc in my program. I think that perhaps MFC had abused casts in VC++ 6, or that the compiler did some magic.
Rewriting the above to use dynamic casts would go like this, and it ends up with a nil pointer, which trips the assert() conditions I wrote here, as I want it to:
CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd);
assert(m_pDoc);
I'm assuming that everybody who has done this before will be able to say "Yeah, of course, they changed that casting behaviour...." but I can't find the documentation for it.
Where possible I'm changing my C++ classes to have a member variable (field) where I store
links to things that it was formerly finding by walking down from the "more or less global" AfxMainWnd().
It would help me to know what changed though, so I can understand what's going on above.
CUserInterfaceDoc is my application's MFC C++ Document class, it is a COleServerDoc which used to be "findable" at runtime with the gross C-style cast at the top.
The above cast still compiles in modern C++ but it's broken, probably due to the fact that the old VC++ 6 compiler did some kind of internal 'magic' with C-style casts that was against the ISO C++ standards. (That's purely a guess on my part).
My question is in two parts:
What's the usual way to get at the CurrentDocument (CFrameWnd::CurrentDocument) from another class that currently has no reference to the main CFrameWnd and had been using the hack I show at the top of this question?
What changed between the non-ISO-compliant VC++ 6 and the more-or-less ISO-compliant later C++ versions that would change the behaviour of the cast expressions above, or did the breakage occur due to MFC internal architecture changes?
My code change:
CUserInterfaceDoc * CMyBrowser::GetUserInterfaceDoc()
{
CUserInterfaceDoc *m_pDoc;
// formerly did this, which works in VC++6 and doesn't work anymore:
//m_pDoc = (CUserInterfaceDoc*)((CFrameWnd *)AfxGetMainWnd())->GetActiveDocument();
assert(m_pMainFrm);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> ( m_pMainFrm->GetActiveDocument() );
assert(m_pDoc);
}
If you are using MFC, you might as well just bite the bullet and use DYNAMIC_DOWNCAST which is an MFC defined macro for casting that's basically equivalent to dynamic_cast.
CFrameWnd* pFrm = DYNAMIC_DOWNCAST(CFrameWnd, AfxGetApp()->m_pMainWnd);
m_pDoc = DYNAMIC_CAST(CUserInterfaceDoc, m_pMainFrm->GetActiveDocument());
In your first rewrite:
CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd);
assert(m_pDoc);
... you simply missed the GetActiveDocument() call which was there in the C-Style cast. So it should work like this:
CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd->GetActiveDocument());
assert(m_pDoc);
DYNAMIC_DOWNCAST is soo oldschool and actually no longer required if you enable RTTI (which is on by default).
See also: MFC DYNAMIC_DOWNCAST vs. dynamic_cast

Resources