简体   繁体   中英

How to use CFSwapInt32BigToHost , CFSwapInt16BigToHost effectively in Swift

I'm working on an app and trying to port an old Obj-C code to Swift. As its related to FileHandling and I've little to no experience on working on it, I'm bit confused on how to do it. That's why I need your help -

This is the method that I'm stuck on. What it does it it reads a file from document directory and then hops offset pointer to read the data.

I want to understand - 1. When and how do we use CFSwapInt32BigToHost and CFSwapInt16BigToHost in Swift? 2. What is UnsafeMutablePointer and how can we initialised it with data.bytes?

- (NSMutableArray *)getTicketFareFrom:(NSString *)fromStation to:(NSString *)toStation{

    NSMutableArray *ticketFareArray = [[NSMutableArray alloc] initWithCapacity:0];

    NSString *directoryPath = @"TrainData/r/";
    NSString* ticketFareFile = @"tf.dat";
    NSString* filePath = [[NSBundle mainBundle] pathForResource:ticketFareFile ofType:@"" inDirectory:directoryPath];

    NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath: filePath];

    if (fileHandle == nil)
        NSLog(@"Failed to open file");

    //Get lenght for station list
    NSData* stationListLenData = [fileHandle readDataOfLength: 4];
    int stationListLength = CFSwapInt32BigToHost(*(int*)([stationListLenData bytes]));

    //Get station list string
    [fileHandle seekToFileOffset: 4];
    NSData* stationListData = [fileHandle readDataOfLength: stationListLength];
    NSString *stationListString =  [[NSString alloc] initWithData:stationListData encoding:NSUTF8StringEncoding];
    _stationListArray = [[NSMutableArray alloc] initWithArray:[stationListString componentsSeparatedByString:@","] copyItems: YES];


    //Get length for via list
    [fileHandle seekToFileOffset: 4 + stationListLength];
    NSData* viaListLenData = [fileHandle readDataOfLength: 4];
    int viaListLength = CFSwapInt32BigToHost(*(int*)([viaListLenData bytes]));

    //get via list string
    [fileHandle seekToFileOffset: 4 + stationListLength + 4];
    NSData* viaListData = [fileHandle readDataOfLength: viaListLength];
    NSString *viaListString =  [[NSString alloc] initWithData:viaListData encoding:NSUTF8StringEncoding];
    _viaRouteArray = [[NSMutableArray alloc] initWithArray:[viaListString componentsSeparatedByString:@","] copyItems: YES];


    NSUInteger fromIndex = [_stationListArray indexOfObject:fromStation];
    NSUInteger toIndex = [_stationListArray indexOfObject:toStation];

    //get length for Ticket fare data
    [fileHandle seekToFileOffset: 4 + stationListLength + 4 + viaListLength];
    NSData *ticketFareLenData = [fileHandle readDataOfLength: 4];
    int faredata_len = CFSwapInt32BigToHost(*(int*)([ticketFareLenData bytes]));


    //get ticket fare data
    [fileHandle seekToFileOffset: 4 + stationListLength + 4 + viaListLength + 4];
    NSData *ticketFareData = [fileHandle readDataOfLength: faredata_len];
    [fileHandle closeFile];

    for (int i = 0; i<faredata_len; i = i+18) {

        unsigned char byte[2];
        int offset = 0;

        // 1.from(int)
        // 2.to(int)
        // 3.via index(int)
        // 4.II(int)
        // 5.II pass monthly(int)
        // 6.II_pass_quarterly(int)
        // 7.I(int)
        // 8.I_pass_monthly(int)
        // 9.I_pass_quarterly(int)

        [ticketFareData getBytes:&byte range:NSMakeRange(i, 2)];
        int from = CFSwapInt16BigToHost(*(int*)(byte));

        offset = offset + 2;
        [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
        int to = CFSwapInt16BigToHost(*(int*)(byte));

        //add if condition for From an To matching
       if (from == fromIndex && to == toIndex) {
            MITicketFare *ticketFare = [[MITicketFare alloc] init];

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int viaIndex = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.viaRoute = [_viaRouteArray objectAtIndex:viaIndex];

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int secondticketfare = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.secondticketfare = secondticketfare;

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int secondpass1mfare = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.secondpass1mfare = secondpass1mfare;

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int secondpass3mfare = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.secondpass3mfare = secondpass3mfare;

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int firstticketfare = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.firstticketfare = firstticketfare;

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int firstpass1mfare = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.firstpass1mfare = firstpass1mfare;

            offset = offset + 2;
            [ticketFareData getBytes:&byte range:NSMakeRange(i + offset, 2)];
            int firstpass3mfare = CFSwapInt16BigToHost(*(int*)(byte));
            ticketFare.firstpass3mfare = firstpass3mfare;

           if (![self isTicketFareDuplicate:ticketFareArray ticketFare:ticketFare]) {
               [ticketFareArray addObject:ticketFare];
           }
        }
    }
    return ticketFareArray;
}

My attempt to port the method -

func getTicketFareFrom(fromStation:String, toStation:String)->Array<TicketFareModel>
    {
        var ticketFareArray:Array<TicketFareModel> = [];

        // Read data from File
        let directoryPath = "TrainData/r/";
        let ticketFareFile = "tf.dat";

        let filePath = NSBundle.mainBundle().pathForResource(ticketFareFile, ofType: "" , inDirectory:directoryPath);
        let fileHandle = NSFileHandle(forReadingAtPath: filePath!);

        if (fileHandle == nil)
        {
            print("Failed to open file");
        }
        else if(fileHandle != nil)
        {
            //Get length for station list
            let stationListLenData:NSData = fileHandle!.readDataOfLength(4);
            let stationListLength:Int = Int(CFSwapInt32BigToHost((stationListLenData.uint32))); // instead of uint32 it should be .bytes

            //Get station list string
            fileHandle!.seekToFileOffset(4);
            let stationListData = fileHandle!.readDataOfLength(stationListLength);
            let stationListString = NSString(data: stationListData, encoding: NSUTF8StringEncoding);

//            self.stationListArray = [String](stationListString.componentsSeparatedByString(","), copyItems: true);
            self.stationListArray = (stationListString!.componentsSeparatedByString(","));

            //Get length for via list
            fileHandle!.seekToFileOffset(UInt64(4 + stationListLength));
            let viaListLenData:NSData = fileHandle!.readDataOfLength(4);
            let viaListLength:Int = Int(CFSwapInt32BigToHost((viaListLenData.uint32)));//CFSwapInt32BigToHost(*(int*)([viaListLenData bytes]));

            //get via list string

            fileHandle!.seekToFileOffset(UInt64(4 + stationListLength + 4));
            let viaListData:NSData = fileHandle!.readDataOfLength(viaListLength);
            let viaListString = NSString(data: viaListData, encoding: NSUTF8StringEncoding);

            self.viaRouteArray = (viaListString!.componentsSeparatedByString(",")); //[[NSMutableArray alloc] initWithArray:[viaListString componentsSeparatedByString:@","] copyItems: YES];

            let fromIndex: Int = self.stationListArray.indexOf(fromStation)!;
            let toIndex: Int = stationListArray.indexOf(toStation)!;

            //get length for Ticket fare data

            fileHandle!.seekToFileOffset(UInt64(4 + stationListLength + 4 + viaListLength));
            let ticketFareLenData:NSData = fileHandle!.readDataOfLength(4);
            let faredata_len:Int = Int(CFSwapInt32BigToHost((ticketFareLenData.uint32))); //int faredata_len = CFSwapInt32BigToHost(*(int*)([ticketFareLenData bytes]));

            //get ticket fare data
            fileHandle!.seekToFileOffset(UInt64(4 + stationListLength + 4 + viaListLength + 4));
            let ticketFareData:NSData = fileHandle!.readDataOfLength(faredata_len);
            fileHandle!.closeFile();
            /* */

            for (var i:Int = 0; i<faredata_len; i = i+18)
            {
                var byte: [UInt8];
                var offset:Int = 0;

                ticketFareData.getBytes(&byte, range: NSMakeRange(i, 2))
                var from: Int = Int(CFSwapInt16BigToHost((ticketFareData.uint16)));//CFSwapInt16BigToHost(Int(&byte))

                offset = offset + 2
                ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))
                var to: Int = CFSwapInt16BigToHost(Int(byte))


                if from == fromIndex && to == toIndex
                {
                    var ticketFareModel: TicketFareModel = TicketFareModel()
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var viaIndex: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.viaRoute = viaRouteArray[viaIndex]
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var secondticketfare: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.secondticketfare = secondticketfare
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var secondpass1mfare: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.secondpass1mfare = secondpass1mfare
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var secondpass3mfare: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.secondpass3mfare = secondpass3mfare
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var firstticketfare: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.firstticketfare = firstticketfare
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var firstpass1mfare: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.firstpass1mfare = firstpass1mfare
                    offset = offset + 2
                    ticketFareData.getBytes(&byte, range: NSMakeRange(i + offset, 2))

                    var firstpass3mfare: Int = CFSwapInt16BigToHost(Int(byte))
                    ticketFareModel.firstpass3mfare = firstpass3mfare

                    if !self.isTicketFareDuplicate(ticketFareArray, ticketFare: ticketFareModel)
                    {
                        ticketFareArray.append(ticketFareModel)
                    }
                }

            }
             //*/
        }
        return ticketFareArray;
    }

I'm stuck in the for loop and I really don't know if I've done the stuff correctly. I've read lots of questions and answers on stackoverflow but nothing came out to be useful for my understanding.

Can anyone please tell me how should I be doing it?

Thanks.

I've done with following codes, it may help you.

let p = UnsafeMutablePointer<UInt32>.allocate(capacity: ((self.buffer?.count)! / 4))
let ptr = UnsafeMutableBufferPointer<UInt32>(start: p, count: ((self.buffer?.count)! / 4))
_ = self.buffer?.copyBytes(to: ptr)
let contentLen = CFSwapInt32BigToHost(UInt32(p.pointee))

self.buffer is a Data? object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM