Retro68/LaunchAPPL/Server/SharedFileStream.cc
2019-01-23 19:41:12 +01:00

138 lines
3.5 KiB
C++

/*
Copyright 2019 Wolfgang Thaller.
This file is part of Retro68.
Retro68 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Retro68 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Retro68. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SharedFileStream.h"
#include <Files.h>
#include <stdio.h>
#include <string.h>
#include <TextUtils.h>
void SharedFileStream::MakeFileName(unsigned char *name, int i)
{
const unsigned char *templ = "\pout_channel_";
memcpy(name, templ, templ[0]+1);
Str31 s;
NumToString(i, s);
memcpy(name + name[0] + 1, s + 1, s[0]);
name[0] += s[0];
}
void SharedFileStream::write(const void* p, size_t n)
{
Str31 name;
MakeFileName(name, outQueueTail++);
HCreate(vRefNum, dirID, name, 'R68L', 'DATA' );
short refNum;
OSErr err = HOpenDF(vRefNum, dirID, name, fsWrDenyPerm, &refNum);
if(err)
return;
long count = n;
FSWrite(refNum, &count, p);
FSClose(refNum);
}
void SharedFileStream::idle()
{
const unsigned char* in_channel = "\pin_channel";
static int count = 0;
if(++count % 10)
return;
short refNum;
OSErr err = HOpenDF(vRefNum, dirID, in_channel, fsRdDenyPerm, &refNum);
if(err == 0)
{
long count, countTotal = 0;
do
{
count = kReadBufferSize;
err = FSRead(refNum, &count, &readBuffer);
countTotal += count;
if((err == noErr || err == eofErr) && count > 0)
notifyReceive(readBuffer, count);
} while(err == noErr);
FSClose(refNum);
#ifdef DEBUG_CONSOLE
printf("read %ld bytes, deleting package\n", countTotal);
#endif
HDelete(vRefNum, dirID, in_channel);
}
if(outQueueTail > outQueueHead)
{
const unsigned char* out_channel = "\pout_channel";
Str31 name;
MakeFileName(name, outQueueHead);
if(HRename(vRefNum, dirID, name, out_channel) == noErr)
++outQueueHead;
}
if(outQueueHead == outQueueTail)
outQueueHead = outQueueTail = 1;
}
bool SharedFileStream::allDataArrived() const
{
return outQueueHead == outQueueTail;
}
SharedFileStream::SharedFileStream(const unsigned char* path)
{
Str255 str;
memcpy(str, path, path[0] + 1);
CInfoPBRec ipb;
ipb.hFileInfo.ioCompletion = nullptr;
ipb.hFileInfo.ioVRefNum = 0;
ipb.hFileInfo.ioNamePtr = str;
ipb.hFileInfo.ioFDirIndex = 0;
ipb.hFileInfo.ioDirID = 0;
PBGetCatInfoSync(&ipb);
dirID = ipb.hFileInfo.ioDirID;
#ifdef DEBUG_CONSOLE
printf("dirID = %ld\n", dirID);
str[str[0]+1] = 0;
printf("name = %s\n", str + 1);
#endif
HParamBlockRec hpb;
hpb.ioParam.ioCompletion = nullptr;
hpb.ioParam.ioVRefNum = 0;
hpb.volumeParam.ioVolIndex = -1;
memcpy(str, path, path[0] + 1);
hpb.volumeParam.ioNamePtr = str;
PBHGetVInfoSync(&hpb);
#ifdef DEBUG_CONSOLE
str[str[0]+1] = 0;
printf("vRefNum = %d, name = %s\n", hpb.volumeParam.ioVRefNum, str + 1);
#endif
vRefNum = hpb.volumeParam.ioVRefNum;
}
SharedFileStream::~SharedFileStream()
{
}