mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
- implemented audio track selection for http
This commit is contained in:
parent
c1cb77c3f8
commit
ab8f0c75f3
5
Makefile
5
Makefile
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Makefile for a Video Disk Recorder plugin
|
# Makefile for a Video Disk Recorder plugin
|
||||||
#
|
#
|
||||||
# $Id: Makefile,v 1.2 2005/02/08 17:22:35 lordjaxom Exp $
|
# $Id: Makefile,v 1.3 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
|
|
||||||
# The official name of this plugin.
|
# The official name of this plugin.
|
||||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||||
@ -48,8 +48,7 @@ DEFINES += -D_GNU_SOURCE
|
|||||||
|
|
||||||
COMMONOBJS = common.o i18n.o \
|
COMMONOBJS = common.o i18n.o \
|
||||||
\
|
\
|
||||||
tools/file.o tools/source.o tools/select.o tools/shared.o tools/socket.o \
|
tools/source.o tools/select.o tools/socket.o tools/tools.o
|
||||||
tools/tools.o
|
|
||||||
|
|
||||||
CLIENTOBJS = $(PLUGIN)-client.o \
|
CLIENTOBJS = $(PLUGIN)-client.o \
|
||||||
\
|
\
|
||||||
|
40
common.c
40
common.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: common.c,v 1.2 2005/02/08 15:34:38 lordjaxom Exp $
|
* $Id: common.c,v 1.3 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/channels.h>
|
#include <vdr/channels.h>
|
||||||
@ -47,8 +47,16 @@ char *GetNextLine(char *String, uint Length, uint &Offset) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cChannel *ChannelFromString(char *String) {
|
const cChannel *ChannelFromString(char *String, int *Apid) {
|
||||||
cChannel *channel = NULL;
|
cChannel *channel = NULL;
|
||||||
|
char *ptr, *end;
|
||||||
|
int apididx = 0;
|
||||||
|
|
||||||
|
if ((ptr = strrchr(String, '+')) != NULL) {
|
||||||
|
*(ptr++) = '\0';
|
||||||
|
apididx = strtoul(ptr, &end, 10);
|
||||||
|
Dprintf("found apididx: %d\n", apididx);
|
||||||
|
}
|
||||||
|
|
||||||
if (isnumber(String)) {
|
if (isnumber(String)) {
|
||||||
int temp = strtol(String, NULL, 10);
|
int temp = strtol(String, NULL, 10);
|
||||||
@ -67,6 +75,34 @@ cChannel *ChannelFromString(char *String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel != NULL && apididx > 0) {
|
||||||
|
int apid = 0, index = 1;
|
||||||
|
const int *apids = channel->Apids();
|
||||||
|
const int *dpids = channel->Dpids();
|
||||||
|
|
||||||
|
for (int i = 0; apids[i] != 0; ++i, ++index) {
|
||||||
|
Dprintf("checking apid %d\n", apids[i]);
|
||||||
|
if (index == apididx) {
|
||||||
|
apid = apids[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apid == 0) {
|
||||||
|
for (int i = 0; dpids[i] != 0; ++i, ++index) {
|
||||||
|
Dprintf("checking dpid %d\n", dpids[i]);
|
||||||
|
if (index == apididx) {
|
||||||
|
apid = dpids[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Apid != NULL)
|
||||||
|
*Apid = apid;
|
||||||
|
}
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
common.h
4
common.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: common.h,v 1.3 2005/02/08 15:34:38 lordjaxom Exp $
|
* $Id: common.h,v 1.4 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_COMMON_H
|
#ifndef VDR_STREAMDEV_COMMON_H
|
||||||
@ -42,7 +42,7 @@ class cChannel;
|
|||||||
|
|
||||||
char *GetNextLine(char *String, uint Length, uint &Offset);
|
char *GetNextLine(char *String, uint Length, uint &Offset);
|
||||||
|
|
||||||
cChannel *ChannelFromString(char *String);
|
const cChannel *ChannelFromString(char *String, int *Apid = NULL);
|
||||||
|
|
||||||
/* Disable logging if BUFCOUNT buffer overflows occur within BUFOVERTIME
|
/* Disable logging if BUFCOUNT buffer overflows occur within BUFOVERTIME
|
||||||
milliseconds. Enable logging again if there is no error within BUFOVERTIME
|
milliseconds. Enable logging again if there is no error within BUFOVERTIME
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionHTTP.c,v 1.5 2005/02/08 19:54:52 lordjaxom Exp $
|
* $Id: connectionHTTP.c,v 1.6 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connectionHTTP.h"
|
#include "server/connectionHTTP.h"
|
||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
cConnectionHTTP::cConnectionHTTP(void): cServerConnection("HTTP") {
|
cConnectionHTTP::cConnectionHTTP(void): cServerConnection("HTTP") {
|
||||||
m_Channel = NULL;
|
m_Channel = NULL;
|
||||||
|
m_Apid = 0;
|
||||||
m_ListChannel = NULL;
|
m_ListChannel = NULL;
|
||||||
m_LiveStreamer = NULL;
|
m_LiveStreamer = NULL;
|
||||||
m_Status = hsRequest;
|
m_Status = hsRequest;
|
||||||
@ -56,7 +57,7 @@ bool cConnectionHTTP::Command(char *Cmd) {
|
|||||||
cDevice *device = GetDevice(m_Channel, 0);
|
cDevice *device = GetDevice(m_Channel, 0);
|
||||||
if (device != NULL) {
|
if (device != NULL) {
|
||||||
device->SwitchChannel(m_Channel, false);
|
device->SwitchChannel(m_Channel, false);
|
||||||
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType)) {
|
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid)) {
|
||||||
m_LiveStreamer->SetDevice(device);
|
m_LiveStreamer->SetDevice(device);
|
||||||
m_Startup = true;
|
m_Startup = true;
|
||||||
if (m_StreamType == stES && (m_Channel->Vpid() == 0
|
if (m_StreamType == stES && (m_Channel->Vpid() == 0
|
||||||
@ -111,8 +112,9 @@ void cConnectionHTTP::Flushed(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionHTTP::CmdGET(char *Opts) {
|
bool cConnectionHTTP::CmdGET(char *Opts) {
|
||||||
cChannel *chan;
|
const cChannel *chan;
|
||||||
char *ep;
|
char *ep;
|
||||||
|
int apid = 0;
|
||||||
|
|
||||||
Opts = skipspace(Opts);
|
Opts = skipspace(Opts);
|
||||||
while (*Opts == '/')
|
while (*Opts == '/')
|
||||||
@ -138,13 +140,17 @@ bool cConnectionHTTP::CmdGET(char *Opts) {
|
|||||||
;
|
;
|
||||||
*ep = '\0';
|
*ep = '\0';
|
||||||
|
|
||||||
|
Dprintf("before channelfromstring\n");
|
||||||
if (strncmp(Opts, "channels.htm", 12) == 0) {
|
if (strncmp(Opts, "channels.htm", 12) == 0) {
|
||||||
m_ListChannel = Channels.First();
|
m_ListChannel = Channels.First();
|
||||||
m_Status = hsHeaders;
|
m_Status = hsHeaders;
|
||||||
} else if ((chan = ChannelFromString(Opts)) != NULL) {
|
} else if ((chan = ChannelFromString(Opts, &apid)) != NULL) {
|
||||||
m_Channel = chan;
|
m_Channel = chan;
|
||||||
|
m_Apid = apid;
|
||||||
|
Dprintf("Apid is %d\n", apid);
|
||||||
m_Status = hsHeaders;
|
m_Status = hsHeaders;
|
||||||
}
|
}
|
||||||
|
Dprintf("after channelfromstring\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionHTTP.h,v 1.1 2004/12/30 22:44:18 lordjaxom Exp $
|
* $Id: connectionHTTP.h,v 1.2 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
|
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
|
||||||
@ -21,8 +21,9 @@ private:
|
|||||||
hsListing,
|
hsListing,
|
||||||
};
|
};
|
||||||
|
|
||||||
cChannel *m_Channel;
|
const cChannel *m_Channel;
|
||||||
cChannel *m_ListChannel;
|
int m_Apid;
|
||||||
|
const cChannel *m_ListChannel;
|
||||||
cStreamdevLiveStreamer *m_LiveStreamer;
|
cStreamdevLiveStreamer *m_LiveStreamer;
|
||||||
eStreamType m_StreamType;
|
eStreamType m_StreamType;
|
||||||
eHTTPStatus m_Status;
|
eHTTPStatus m_Status;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionVTP.c,v 1.4 2005/02/08 17:22:35 lordjaxom Exp $
|
* $Id: connectionVTP.c,v 1.5 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connectionVTP.h"
|
#include "server/connectionVTP.h"
|
||||||
@ -92,7 +92,7 @@ bool cConnectionVTP::CmdCAPS(char *Opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionVTP::CmdPROV(char *Opts) {
|
bool cConnectionVTP::CmdPROV(char *Opts) {
|
||||||
cChannel *chan;
|
const cChannel *chan;
|
||||||
int prio;
|
int prio;
|
||||||
char *ep;
|
char *ep;
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "remux/ts2es.h"
|
#include "remux/ts2es.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
// --- cStreamdevLiveReceiver -------------------------------------------------
|
||||||
|
|
||||||
cStreamdevLiveReceiver::cStreamdevLiveReceiver(cStreamdevLiveStreamer *Streamer, int Ca,
|
cStreamdevLiveReceiver::cStreamdevLiveReceiver(cStreamdevLiveStreamer *Streamer, int Ca,
|
||||||
int Priority, const int *Pids):
|
int Priority, const int *Pids):
|
||||||
cReceiver(Ca, Priority, 0, Pids),
|
cReceiver(Ca, Priority, 0, Pids),
|
||||||
@ -18,30 +20,29 @@ cStreamdevLiveReceiver::~cStreamdevLiveReceiver()
|
|||||||
Detach();
|
Detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevLiveReceiver::Activate(bool On)
|
|
||||||
{
|
|
||||||
m_Streamer->Activate(On);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevLiveReceiver::Receive(uchar *Data, int Length) {
|
void cStreamdevLiveReceiver::Receive(uchar *Data, int Length) {
|
||||||
int p = m_Streamer->Receive(Data, Length);
|
int p = m_Streamer->Receive(Data, Length);
|
||||||
if (p != Length)
|
if (p != Length)
|
||||||
m_Streamer->ReportOverflow(Length - p);
|
m_Streamer->ReportOverflow(Length - p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cStreamdevLiveStreamer -------------------------------------------------
|
||||||
|
|
||||||
cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority):
|
cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority):
|
||||||
cStreamdevStreamer("streamdev-livestreaming") {
|
cStreamdevStreamer("streamdev-livestreaming"),
|
||||||
m_Priority = Priority;
|
m_Priority(Priority),
|
||||||
m_NumPids = 0;
|
m_NumPids(0),
|
||||||
m_StreamType = stTSPIDS;
|
m_StreamType(stTSPIDS),
|
||||||
m_Channel = NULL;
|
m_Channel(NULL),
|
||||||
m_Device = NULL;
|
m_Device(NULL),
|
||||||
m_Receiver = NULL;
|
m_Receiver(NULL),
|
||||||
m_Remux = NULL;
|
m_PESRemux(NULL),
|
||||||
m_PESRemux = NULL;
|
m_Remux(NULL)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cStreamdevLiveStreamer::~cStreamdevLiveStreamer() {
|
cStreamdevLiveStreamer::~cStreamdevLiveStreamer()
|
||||||
|
{
|
||||||
Dprintf("Desctructing Live streamer\n");
|
Dprintf("Desctructing Live streamer\n");
|
||||||
delete m_Receiver;
|
delete m_Receiver;
|
||||||
delete m_Remux;
|
delete m_Remux;
|
||||||
@ -50,21 +51,12 @@ cStreamdevLiveStreamer::~cStreamdevLiveStreamer() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevLiveStreamer::Detach(void) {
|
bool cStreamdevLiveStreamer::SetPid(int Pid, bool On)
|
||||||
m_Device->Detach(m_Receiver);
|
{
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevLiveStreamer::Attach(void) {
|
|
||||||
m_Device->AttachReceiver(m_Receiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevLiveStreamer::Start(cTBSocket *Socket) {
|
|
||||||
Dprintf("LIVESTREAMER START\n");
|
|
||||||
cStreamdevStreamer::Start(Socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cStreamdevLiveStreamer::SetPid(int Pid, bool On) {
|
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
|
if (Pid == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (On) {
|
if (On) {
|
||||||
for (idx = 0; idx < m_NumPids; ++idx) {
|
for (idx = 0; idx < m_NumPids; ++idx) {
|
||||||
@ -100,7 +92,7 @@ bool cStreamdevLiveStreamer::SetPid(int Pid, bool On) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType StreamType)
|
bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType StreamType, int Apid)
|
||||||
{
|
{
|
||||||
Dprintf("Initializing Remuxer for full channel transfer\n");
|
Dprintf("Initializing Remuxer for full channel transfer\n");
|
||||||
printf("ca pid: %d\n", Channel->Ca());
|
printf("ca pid: %d\n", Channel->Ca());
|
||||||
@ -109,29 +101,38 @@ bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType Str
|
|||||||
switch (m_StreamType) {
|
switch (m_StreamType) {
|
||||||
case stES:
|
case stES:
|
||||||
{
|
{
|
||||||
int pid = ISRADIO(Channel) ? Channel->Apid(0) : Channel->Vpid();
|
int pid = ISRADIO(m_Channel) ? m_Channel->Apid(0) : m_Channel->Vpid();
|
||||||
|
if (Apid != 0)
|
||||||
|
pid = Apid;
|
||||||
m_Remux = new cTS2ESRemux(pid);
|
m_Remux = new cTS2ESRemux(pid);
|
||||||
return SetPid(pid, true);
|
return SetPid(pid, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
case stPES:
|
case stPES:
|
||||||
m_PESRemux = new cRemux(Channel->Vpid(), Channel->Apids(), Channel->Dpids(),
|
Dprintf("PES\n");
|
||||||
Channel->Spids(), false);
|
m_PESRemux = new cRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(),
|
||||||
return SetPid(Channel->Vpid(), true)
|
m_Channel->Spids(), false);
|
||||||
&& SetPid(Channel->Apid(0), true)
|
if (Apid != 0)
|
||||||
&& SetPid(Channel->Apid(1), true)
|
return SetPid(m_Channel->Vpid(), true)
|
||||||
&& SetPid(Channel->Dpid(0), true);
|
&& SetPid(Apid, true);
|
||||||
|
else
|
||||||
|
return SetPid(m_Channel->Vpid(), true)
|
||||||
|
&& SetPid(m_Channel->Apid(0), true)
|
||||||
|
&& SetPid(m_Channel->Dpid(0), true);
|
||||||
|
|
||||||
case stPS:
|
case stPS:
|
||||||
m_Remux = new cTS2PSRemux(Channel->Vpid(), Channel->Apid(0), 0, 0, 0, true);
|
m_Remux = new cTS2PSRemux(m_Channel->Vpid(), m_Channel->Apid(0), 0, 0, 0, true);
|
||||||
return SetPid(Channel->Vpid(), true)
|
return SetPid(m_Channel->Vpid(), true)
|
||||||
&& SetPid(Channel->Apid(0), true);
|
&& SetPid(m_Channel->Apid(0), true);
|
||||||
|
|
||||||
case stTS:
|
case stTS:
|
||||||
return SetPid(Channel->Vpid(), true)
|
if (Apid != 0)
|
||||||
&& SetPid(Channel->Apid(0), true)
|
return SetPid(m_Channel->Vpid(), true)
|
||||||
&& SetPid(Channel->Apid(1), true)
|
&& SetPid(Apid, true);
|
||||||
&& SetPid(Channel->Dpid(0), true);
|
else
|
||||||
|
return SetPid(m_Channel->Vpid(), true)
|
||||||
|
&& SetPid(m_Channel->Apid(0), true)
|
||||||
|
&& SetPid(m_Channel->Dpid(0), true);
|
||||||
|
|
||||||
case stTSPIDS:
|
case stTSPIDS:
|
||||||
Dprintf("pid streaming mode\n");
|
Dprintf("pid streaming mode\n");
|
||||||
@ -140,8 +141,8 @@ bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType Str
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cStreamdevLiveStreamer::SetFilter(u_short Pid, u_char Tid, u_char Mask,
|
bool cStreamdevLiveStreamer::SetFilter(u_short Pid, u_char Tid, u_char Mask, bool On)
|
||||||
bool On) {
|
{
|
||||||
#if 0
|
#if 0
|
||||||
Dprintf("setting filter\n");
|
Dprintf("setting filter\n");
|
||||||
if (On) {
|
if (On) {
|
||||||
@ -195,49 +196,19 @@ void cStreamdevLiveStreamer::Del(int Count)
|
|||||||
case stTS:
|
case stTS:
|
||||||
case stTSPIDS:
|
case stTSPIDS:
|
||||||
cStreamdevStreamer::Del(Count);
|
cStreamdevStreamer::Del(Count);
|
||||||
|
break;
|
||||||
|
|
||||||
case stPES:
|
case stPES:
|
||||||
m_PESRemux->Del(Count);
|
m_PESRemux->Del(Count);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remuxer einbinden
|
std::string cStreamdevLiveStreamer::Report(void)
|
||||||
#if 0
|
{
|
||||||
uchar *cStreamdevLiveStreamer::Process(const uchar *Data, int &Count, int &Result) {
|
|
||||||
uchar *remuxed = m_Remux != NULL ? m_Remux->Process(Data, Count, Result)
|
|
||||||
: cStreamdevStreamer::Process(Data, Count, Result);
|
|
||||||
if (remuxed) {
|
|
||||||
/*if (Socket()->Type() == SOCK_DGRAM) {
|
|
||||||
free(m_Buffer);
|
|
||||||
Result += 12;
|
|
||||||
m_Buffer = MALLOC(uchar, Result);
|
|
||||||
m_Buffer[0] = 0x01;
|
|
||||||
m_Buffer[1] = 0x02;
|
|
||||||
m_Buffer[2] = 0x03;
|
|
||||||
m_Buffer[3] = 0x04;
|
|
||||||
m_Buffer[4] = (Result & 0xff000000) >> 24;
|
|
||||||
m_Buffer[5] = (Result & 0xff0000) >> 16;
|
|
||||||
m_Buffer[6] = (Result & 0xff00) >> 8;
|
|
||||||
m_Buffer[7] = (Result & 0xff);
|
|
||||||
m_Buffer[8] = (m_Sequence & 0xff000000) >> 24;
|
|
||||||
m_Buffer[9] = (m_Sequence & 0xff0000) >> 16;
|
|
||||||
m_Buffer[10] = (m_Sequence & 0xff00) >> 8;
|
|
||||||
m_Buffer[11] = (m_Sequence & 0xff);
|
|
||||||
memcpy(m_Buffer + 12, Data, Result - 12);
|
|
||||||
if (m_Sequence++ == 0x7fffffff)
|
|
||||||
m_Sequence = 0;
|
|
||||||
return m_Buffer;
|
|
||||||
}*/
|
|
||||||
return remuxed;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string cStreamdevLiveStreamer::Report(void) {
|
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
if (m_Device != NULL)
|
if (m_Device != NULL)
|
||||||
|
@ -8,13 +8,11 @@
|
|||||||
#include "server/livefilter.h"
|
#include "server/livefilter.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#if MAXRECEIVEPIDS < 16
|
|
||||||
# error Too few receiver pids allowed! Please contact sascha@akv-soft.de!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class cTSRemux;
|
class cTSRemux;
|
||||||
class cRemux;
|
class cRemux;
|
||||||
|
|
||||||
|
// --- cStreamdevLiveReceiver -------------------------------------------------
|
||||||
|
|
||||||
class cStreamdevLiveReceiver: public cReceiver {
|
class cStreamdevLiveReceiver: public cReceiver {
|
||||||
friend class cStreamdevLiveStreamer;
|
friend class cStreamdevLiveStreamer;
|
||||||
|
|
||||||
@ -26,11 +24,12 @@ protected:
|
|||||||
virtual void Receive(uchar *Data, int Length);
|
virtual void Receive(uchar *Data, int Length);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevLiveReceiver(cStreamdevLiveStreamer *Streamer, int Ca, int Priority,
|
cStreamdevLiveReceiver(cStreamdevLiveStreamer *Streamer, int Ca, int Priority, const int *Pids);
|
||||||
const int *Pids);
|
|
||||||
virtual ~cStreamdevLiveReceiver();
|
virtual ~cStreamdevLiveReceiver();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- cStreamdevLiveStreamer -------------------------------------------------
|
||||||
|
|
||||||
class cStreamdevLiveStreamer: public cStreamdevStreamer {
|
class cStreamdevLiveStreamer: public cStreamdevStreamer {
|
||||||
private:
|
private:
|
||||||
int m_Priority;
|
int m_Priority;
|
||||||
@ -42,7 +41,6 @@ private:
|
|||||||
cStreamdevLiveReceiver *m_Receiver;
|
cStreamdevLiveReceiver *m_Receiver;
|
||||||
cRemux *m_PESRemux;
|
cRemux *m_PESRemux;
|
||||||
cTSRemux *m_Remux;
|
cTSRemux *m_Remux;
|
||||||
uchar *m_Buffer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevLiveStreamer(int Priority);
|
cStreamdevLiveStreamer(int Priority);
|
||||||
@ -50,20 +48,26 @@ public:
|
|||||||
|
|
||||||
void SetDevice(cDevice *Device) { m_Device = Device; }
|
void SetDevice(cDevice *Device) { m_Device = Device; }
|
||||||
bool SetPid(int Pid, bool On);
|
bool SetPid(int Pid, bool On);
|
||||||
bool SetChannel(const cChannel *Channel, eStreamType StreamType);
|
bool SetChannel(const cChannel *Channel, eStreamType StreamType, int Apid = 0);
|
||||||
bool SetFilter(u_short Pid, u_char Tid, u_char Mask, bool On);
|
bool SetFilter(u_short Pid, u_char Tid, u_char Mask, bool On);
|
||||||
|
|
||||||
virtual int Put(const uchar *Data, int Count);
|
virtual int Put(const uchar *Data, int Count);
|
||||||
virtual uchar *Get(int &Count);
|
virtual uchar *Get(int &Count);
|
||||||
virtual void Del(int Count);
|
virtual void Del(int Count);
|
||||||
|
|
||||||
virtual void Detach(void);
|
virtual void Attach(void) { Dprintf("attach %p\n", m_Device);m_Device->AttachReceiver(m_Receiver); }
|
||||||
virtual void Attach(void);
|
virtual void Detach(void) { m_Device->Detach(m_Receiver); }
|
||||||
|
|
||||||
virtual void Start(cTBSocket *Socket);
|
|
||||||
|
|
||||||
// Statistical purposes:
|
// Statistical purposes:
|
||||||
virtual std::string Report(void);
|
virtual std::string Report(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- cStreamdevLiveReceiver reverse inlines ---------------------------------
|
||||||
|
|
||||||
|
inline void cStreamdevLiveReceiver::Activate(bool On)
|
||||||
|
{
|
||||||
|
Dprintf("LiveReceiver->Activate()\n");
|
||||||
|
m_Streamer->Activate(On);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // VDR_STREAMDEV_LIVESTREAMER_H
|
#endif // VDR_STREAMDEV_LIVESTREAMER_H
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamer.c,v 1.5 2005/02/09 19:47:09 lordjaxom Exp $
|
* $Id: streamer.c,v 1.6 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/ringbuffer.h>
|
#include <vdr/ringbuffer.h>
|
||||||
@ -13,6 +13,8 @@
|
|||||||
#include "tools/socket.h"
|
#include "tools/socket.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
// --- cStreamdevWriter -------------------------------------------------------
|
||||||
|
|
||||||
cStreamdevWriter::cStreamdevWriter(cTBSocket *Socket, cStreamdevStreamer *Streamer):
|
cStreamdevWriter::cStreamdevWriter(cTBSocket *Socket, cStreamdevStreamer *Streamer):
|
||||||
cThread("streamdev-writer"),
|
cThread("streamdev-writer"),
|
||||||
m_Streamer(Streamer),
|
m_Streamer(Streamer),
|
||||||
@ -29,6 +31,7 @@ cStreamdevWriter::~cStreamdevWriter()
|
|||||||
|
|
||||||
void cStreamdevWriter::Action(void)
|
void cStreamdevWriter::Action(void)
|
||||||
{
|
{
|
||||||
|
Dprintf("Writer start\n");
|
||||||
int max = 0;
|
int max = 0;
|
||||||
m_Active = true;
|
m_Active = true;
|
||||||
while (m_Active) {
|
while (m_Active) {
|
||||||
@ -49,13 +52,15 @@ void cStreamdevWriter::Action(void)
|
|||||||
Dprintf("Max. Transmit Blocksize was: %d\n", max);
|
Dprintf("Max. Transmit Blocksize was: %d\n", max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cStreamdevStreamer -----------------------------------------------------
|
||||||
|
|
||||||
cStreamdevStreamer::cStreamdevStreamer(const char *Name):
|
cStreamdevStreamer::cStreamdevStreamer(const char *Name):
|
||||||
cThread(Name),
|
cThread(Name),
|
||||||
m_Active(false),
|
m_Active(false),
|
||||||
m_Writer(NULL),
|
m_Writer(NULL),
|
||||||
m_RingBuffer(new cRingBufferLinear(STREAMERBUFSIZE, TS_SIZE * 2, true,
|
m_RingBuffer(new cRingBufferLinear(STREAMERBUFSIZE, TS_SIZE * 2, true,
|
||||||
"streamdev-streamer")),
|
"streamdev-streamer")),
|
||||||
m_SendBuffer(new cRingBufferLinear(WRITERBUFSIZE, MAXTRANSMITBLOCKSIZE))
|
m_SendBuffer(new cRingBufferLinear(WRITERBUFSIZE, TS_SIZE * 2))
|
||||||
{
|
{
|
||||||
m_RingBuffer->SetTimeouts(0, 100);
|
m_RingBuffer->SetTimeouts(0, 100);
|
||||||
m_SendBuffer->SetTimeouts(0, 100);
|
m_SendBuffer->SetTimeouts(0, 100);
|
||||||
@ -71,12 +76,14 @@ cStreamdevStreamer::~cStreamdevStreamer()
|
|||||||
|
|
||||||
void cStreamdevStreamer::Start(cTBSocket *Socket)
|
void cStreamdevStreamer::Start(cTBSocket *Socket)
|
||||||
{
|
{
|
||||||
|
Dprintf("start streamer\n");
|
||||||
m_Writer = new cStreamdevWriter(Socket, this);
|
m_Writer = new cStreamdevWriter(Socket, this);
|
||||||
Attach();
|
Attach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevStreamer::Activate(bool On)
|
void cStreamdevStreamer::Activate(bool On)
|
||||||
{
|
{
|
||||||
|
Dprintf("activate streamer\n");
|
||||||
if (On && !m_Active) {
|
if (On && !m_Active) {
|
||||||
m_Writer->Start();
|
m_Writer->Start();
|
||||||
cThread::Start();
|
cThread::Start();
|
||||||
@ -92,21 +99,6 @@ void cStreamdevStreamer::Stop(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cStreamdevStreamer::Put(const uchar *Data, int Count)
|
|
||||||
{
|
|
||||||
return m_SendBuffer->Put(Data, Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
uchar *cStreamdevStreamer::Get(int &Count)
|
|
||||||
{
|
|
||||||
return m_SendBuffer->Get(Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevStreamer::Del(int Count)
|
|
||||||
{
|
|
||||||
return m_SendBuffer->Del(Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevStreamer::Action(void)
|
void cStreamdevStreamer::Action(void)
|
||||||
{
|
{
|
||||||
int max = 0;
|
int max = 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamer.h,v 1.3 2005/02/08 19:54:52 lordjaxom Exp $
|
* $Id: streamer.h,v 1.4 2005/02/10 22:24:26 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_STREAMER_H
|
#ifndef VDR_STREAMDEV_STREAMER_H
|
||||||
@ -12,10 +12,11 @@
|
|||||||
class cTBSocket;
|
class cTBSocket;
|
||||||
class cStreamdevStreamer;
|
class cStreamdevStreamer;
|
||||||
|
|
||||||
#define MAXTRANSMITBLOCKSIZE TS_SIZE*10
|
|
||||||
#define STREAMERBUFSIZE MEGABYTE(4)
|
#define STREAMERBUFSIZE MEGABYTE(4)
|
||||||
#define WRITERBUFSIZE KILOBYTE(192)
|
#define WRITERBUFSIZE KILOBYTE(192)
|
||||||
|
|
||||||
|
// --- cStreamdevWriter -------------------------------------------------------
|
||||||
|
|
||||||
class cStreamdevWriter: public cThread {
|
class cStreamdevWriter: public cThread {
|
||||||
private:
|
private:
|
||||||
cStreamdevStreamer *m_Streamer;
|
cStreamdevStreamer *m_Streamer;
|
||||||
@ -30,6 +31,8 @@ public:
|
|||||||
virtual ~cStreamdevWriter();
|
virtual ~cStreamdevWriter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- cStreamdevStreamer -----------------------------------------------------
|
||||||
|
|
||||||
class cStreamdevStreamer: public cThread {
|
class cStreamdevStreamer: public cThread {
|
||||||
private:
|
private:
|
||||||
bool m_Active;
|
bool m_Active;
|
||||||
@ -40,8 +43,6 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
|
|
||||||
//const cTBSocket *Socket(void) const { return m_Socket; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevStreamer(const char *Name);
|
cStreamdevStreamer(const char *Name);
|
||||||
virtual ~cStreamdevStreamer();
|
virtual ~cStreamdevStreamer();
|
||||||
@ -53,9 +54,9 @@ public:
|
|||||||
int Receive(uchar *Data, int Length) { return m_RingBuffer->Put(Data, Length); }
|
int Receive(uchar *Data, int Length) { return m_RingBuffer->Put(Data, Length); }
|
||||||
void ReportOverflow(int Bytes) { m_RingBuffer->ReportOverflow(Bytes); }
|
void ReportOverflow(int Bytes) { m_RingBuffer->ReportOverflow(Bytes); }
|
||||||
|
|
||||||
virtual int Put(const uchar *Data, int Count);
|
virtual int Put(const uchar *Data, int Count) { return m_SendBuffer->Put(Data, Count); }
|
||||||
virtual uchar *Get(int &Count);
|
virtual uchar *Get(int &Count) { return m_SendBuffer->Get(Count); }
|
||||||
virtual void Del(int Count);
|
virtual void Del(int Count) { m_SendBuffer->Del(Count); }
|
||||||
|
|
||||||
virtual void Detach(void) = 0;
|
virtual void Detach(void) = 0;
|
||||||
virtual void Attach(void) = 0;
|
virtual void Attach(void) = 0;
|
||||||
|
96
tools/file.c
96
tools/file.c
@ -1,96 +0,0 @@
|
|||||||
#include "tools/file.h"
|
|
||||||
|
|
||||||
#include <vdr/tools.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
cTBFile::cTBFile(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBFile::~cTBFile() {
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cTBFile::Open(const std::string &Filename, int Mode, mode_t Attribs) {
|
|
||||||
int filed;
|
|
||||||
|
|
||||||
if (IsOpen()) Close();
|
|
||||||
|
|
||||||
if ((filed = ::open(Filename.c_str(), Mode, Attribs)) == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!cTBSource::Open(filed))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_Filename = Filename;
|
|
||||||
m_Anonymous = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cTBFile::Open(uint Fileno) {
|
|
||||||
if (IsOpen()) Close();
|
|
||||||
|
|
||||||
if (!cTBSource::Open(Fileno))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_Filename = (std::string)"<&" + (const char*)itoa(Fileno) + ">";
|
|
||||||
m_Anonymous = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cTBFile::Close(void) {
|
|
||||||
bool ret = true;
|
|
||||||
|
|
||||||
if (!IsOpen())
|
|
||||||
ERRNUL(EBADF);
|
|
||||||
|
|
||||||
if (::close(*this) == -1)
|
|
||||||
ret = false;
|
|
||||||
|
|
||||||
if (!cTBSource::Close())
|
|
||||||
ret = false;
|
|
||||||
|
|
||||||
m_Filename = "";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cTBFile::Unlink(void) const {
|
|
||||||
if (m_Filename == "")
|
|
||||||
ERRNUL(ENOENT);
|
|
||||||
|
|
||||||
if (!IsOpen())
|
|
||||||
ERRNUL(EBADF);
|
|
||||||
|
|
||||||
if (m_Anonymous)
|
|
||||||
ERRNUL(EINVAL);
|
|
||||||
|
|
||||||
return cTBFile::Unlink(m_Filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cTBFile::Unlink(const std::string &Filename) {
|
|
||||||
return (::unlink(Filename.c_str()) != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t cTBFile::Size(void) const {
|
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
if (!IsOpen())
|
|
||||||
ERRSYS(EBADF);
|
|
||||||
|
|
||||||
if (fstat(*this, &buf) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return buf.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t cTBFile::Size(const std::string &Filename) {
|
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
if (stat(Filename.c_str(), &buf) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return buf.st_size;
|
|
||||||
}
|
|
100
tools/file.h
100
tools/file.h
@ -1,100 +0,0 @@
|
|||||||
#ifndef TOOLBOX_FILE_H
|
|
||||||
#define TOOLBOX_FILE_H
|
|
||||||
|
|
||||||
#include "tools/tools.h"
|
|
||||||
#include "tools/source.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/* cTBFile provides a cTBSource-derived interface for input and output on UNIX
|
|
||||||
files. */
|
|
||||||
|
|
||||||
class cTBFile: public cTBSource {
|
|
||||||
private:
|
|
||||||
bool m_Anonymous;
|
|
||||||
std::string m_Filename;
|
|
||||||
|
|
||||||
/* Unhide and forbid baseclass method */
|
|
||||||
virtual bool Open(int Fd, bool IsUnixFd = false) { return false; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
cTBFile(void);
|
|
||||||
virtual ~cTBFile();
|
|
||||||
|
|
||||||
/* enum eFileType represents the modes a file can be opened with. The full
|
|
||||||
open mode is one of the first three, maybe or'ed with one of the others.
|
|
||||||
*/
|
|
||||||
enum eFileType {
|
|
||||||
ReadOnly = O_RDONLY,
|
|
||||||
WriteOnly = O_WRONLY,
|
|
||||||
ReadWrite = O_RDWR,
|
|
||||||
|
|
||||||
Create = O_CREAT,
|
|
||||||
Exclude = O_EXCL,
|
|
||||||
Truncate = O_TRUNC,
|
|
||||||
Append = O_APPEND
|
|
||||||
};
|
|
||||||
|
|
||||||
/* See cTBSource::SysRead()
|
|
||||||
Reimplemented for UNIX files. */
|
|
||||||
virtual ssize_t SysRead(void *Buffer, size_t Length) const;
|
|
||||||
|
|
||||||
/* See cTBSource::SysWrite()
|
|
||||||
Reimplemented for UNIX files. */
|
|
||||||
virtual ssize_t SysWrite(const void *Buffer, size_t Length) const;
|
|
||||||
|
|
||||||
/* Open() opens the file referred to by Filename according to the given
|
|
||||||
Mode. If the file is created, it receives the attributes given by
|
|
||||||
Attribs, defaulting to rw-------. Returns true on success and false on
|
|
||||||
error, setting errno appropriately. */
|
|
||||||
virtual bool Open(const std::string &Filename, int Mode,
|
|
||||||
mode_t Attribs = S_IRUSR + S_IWUSR);
|
|
||||||
|
|
||||||
/* Open() associates this file object with Fileno. Fileno must refer to a
|
|
||||||
previously opened file descriptor, which will be set non-blocking by
|
|
||||||
this call. If successful, true is returned, false otherwise and errno
|
|
||||||
is set appropriately. */
|
|
||||||
virtual bool Open(uint Fileno);
|
|
||||||
|
|
||||||
/* Close() closes the associated file descriptor and releases all
|
|
||||||
structures. Returns true on success and false otherwise, setting errno
|
|
||||||
appropriately. The object is in the closed state afterwards, even if
|
|
||||||
an error occured. */
|
|
||||||
virtual bool Close(void);
|
|
||||||
|
|
||||||
/* Unlink() unlinks (deletes) the associated file from the underlying
|
|
||||||
filesystem. Returns true on success and false otherwise, setting errno
|
|
||||||
appropriately. The file must be opened by filename to use this. */
|
|
||||||
virtual bool Unlink(void) const;
|
|
||||||
|
|
||||||
/* Unlink() unlinks (deletes) the file referred to by Filename from the
|
|
||||||
underlying filesystem. Returns true on success and false otherwise,
|
|
||||||
setting errno appropriately. */
|
|
||||||
static bool Unlink(const std::string &Filename);
|
|
||||||
|
|
||||||
/* Size() returns the current size of the associated file. Returns the
|
|
||||||
exact size of the file in bytes. Returns -1 on error, setting errno to
|
|
||||||
an appropriate value. */
|
|
||||||
virtual ssize_t Size(void) const;
|
|
||||||
|
|
||||||
/* Size() returns the current size of the file referred to by Filename.
|
|
||||||
Symbolic links are followed (the size of the link-target is returned).
|
|
||||||
Returns the exact size of the file in bytes. Returns -1 on error,
|
|
||||||
setting errno to an appropriate value. */
|
|
||||||
static ssize_t Size(const std::string &Filename);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline ssize_t cTBFile::SysRead(void *Buffer, size_t Length) const {
|
|
||||||
return ::read(*this, Buffer, Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ssize_t cTBFile::SysWrite(const void *Buffer, size_t Length) const {
|
|
||||||
return ::write(*this, Buffer, Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // TOOLBOX_FILE_H
|
|
@ -1,90 +0,0 @@
|
|||||||
#include "tools/shared.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
cSharedData *cSharedData::Construct (size_t Length) {
|
|
||||||
size_t reallength = sizeof(cSharedData) + Length;
|
|
||||||
cSharedData *ret = (cSharedData*)new char[reallength];
|
|
||||||
|
|
||||||
ret->m_Length = Length;
|
|
||||||
ret->m_NumRefs = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBShared::cTBShared(void) {
|
|
||||||
m_Buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBShared::cTBShared (const cTBShared &src) {
|
|
||||||
m_Buffer = src.m_Buffer;
|
|
||||||
if (m_Buffer)
|
|
||||||
++*m_Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBShared::~cTBShared () {
|
|
||||||
if (m_Buffer)
|
|
||||||
Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBShared::Clear () {
|
|
||||||
if (m_Buffer)
|
|
||||||
Release();
|
|
||||||
m_Buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBShared::Set (const cTBShared &src) {
|
|
||||||
if (m_Buffer)
|
|
||||||
Release();
|
|
||||||
|
|
||||||
m_Buffer = src.m_Buffer;
|
|
||||||
if (m_Buffer)
|
|
||||||
++*m_Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBShared::Release () {
|
|
||||||
CHECK_PTR(m_Buffer);
|
|
||||||
|
|
||||||
if (--*m_Buffer == 0)
|
|
||||||
delete[] (char*)m_Buffer;
|
|
||||||
|
|
||||||
m_Buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBShared::Release(uint newsize) {
|
|
||||||
CHECK_PTR(m_Buffer);
|
|
||||||
|
|
||||||
Allocate(newsize, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBShared::Exclusive () {
|
|
||||||
CHECK_PTR(m_Buffer);
|
|
||||||
|
|
||||||
if (m_Buffer->Refs() == 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cSharedData *copy = cSharedData::Construct(m_Buffer->Size());
|
|
||||||
memcpy(*copy, *m_Buffer, m_Buffer->Size());
|
|
||||||
|
|
||||||
Release();
|
|
||||||
|
|
||||||
m_Buffer = copy;
|
|
||||||
++*m_Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBShared::Allocate (size_t len, bool keep /* = false */) {
|
|
||||||
if (m_Buffer && (m_Buffer->Refs() == 1) && (m_Buffer->Size() == len))
|
|
||||||
return;
|
|
||||||
|
|
||||||
cSharedData *newBuffer = cSharedData::Construct(len);
|
|
||||||
if (m_Buffer) {
|
|
||||||
if (keep)
|
|
||||||
memcpy(*newBuffer, *m_Buffer, len < m_Buffer->Size() ? len : m_Buffer->Size());
|
|
||||||
|
|
||||||
Release();
|
|
||||||
}
|
|
||||||
m_Buffer = newBuffer;
|
|
||||||
++*m_Buffer;
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
|||||||
#ifndef TOOLBOX_SHARED_H
|
|
||||||
#define TOOLBOX_SHARED_H
|
|
||||||
|
|
||||||
#include "tools/tools.h"
|
|
||||||
|
|
||||||
struct cSharedData {
|
|
||||||
private:
|
|
||||||
uint m_Length;
|
|
||||||
uint m_NumRefs;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static cSharedData *Construct (size_t Length);
|
|
||||||
|
|
||||||
operator char * () { return this ? (char*)(this+1) : 0; }
|
|
||||||
|
|
||||||
uint operator++ () { return ++m_NumRefs; }
|
|
||||||
uint operator-- () { return --m_NumRefs; }
|
|
||||||
|
|
||||||
size_t Size() const { return m_Length; }
|
|
||||||
|
|
||||||
uint Refs () const { return m_NumRefs; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class cTBShared {
|
|
||||||
private:
|
|
||||||
cSharedData *m_Buffer;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void Release();
|
|
||||||
void Exclusive();
|
|
||||||
void Allocate(size_t len, bool keep = false);
|
|
||||||
|
|
||||||
char *Buffer() const { return m_Buffer ? (char*)*m_Buffer : (char*)0; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
cTBShared (void);
|
|
||||||
cTBShared (const cTBShared &src);
|
|
||||||
virtual ~cTBShared ();
|
|
||||||
|
|
||||||
virtual void Clear ();
|
|
||||||
virtual void Set (const cTBShared &src);
|
|
||||||
|
|
||||||
virtual char *Buffer (uint size);
|
|
||||||
virtual void Release (uint newsize);
|
|
||||||
|
|
||||||
cTBShared &operator= (const cTBShared &src) { Set(src); return *this; }
|
|
||||||
|
|
||||||
operator const void * () const { return m_Buffer ? (const void*)*m_Buffer : (const void*)0; }
|
|
||||||
operator void * () const { return m_Buffer ? (void*)*m_Buffer : (void*)0; }
|
|
||||||
|
|
||||||
operator const char * () const { return m_Buffer ? (const char*)*m_Buffer : (const char*)0; }
|
|
||||||
|
|
||||||
size_t Size() const { return m_Buffer ? m_Buffer->Size() : 0; }
|
|
||||||
size_t Length() const { return m_Buffer ? m_Buffer->Size() : 0; }
|
|
||||||
|
|
||||||
// friend cSource &operator>> (cSource &dest, cTBShared &str);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline char *cTBShared::Buffer(uint size) {
|
|
||||||
if ((!m_Buffer) || (m_Buffer->Refs() > 1) || (size > m_Buffer->Size()))
|
|
||||||
Allocate(size, true);
|
|
||||||
return Buffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TOOLBOX_SHARED_H
|
|
454
tools/string.c
454
tools/string.c
@ -1,454 +0,0 @@
|
|||||||
#include "tools/string.h"
|
|
||||||
#ifdef TOOLBOX_REGEX
|
|
||||||
# include "tools/regex.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
const cTBString cTBString::Null;
|
|
||||||
|
|
||||||
cTBString::cTBString():
|
|
||||||
cTBShared(),
|
|
||||||
m_StringLen(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBString::cTBString(const cTBString &src):
|
|
||||||
cTBShared(src),
|
|
||||||
m_StringLen(src.m_StringLen) {
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBString::cTBString(const char *src) {
|
|
||||||
Set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBString::cTBString(const uchar *src) {
|
|
||||||
Set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBString::cTBString(char src) {
|
|
||||||
Set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
cTBString::~cTBString () {
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Release(uint newsize) {
|
|
||||||
m_StringLen = newsize;
|
|
||||||
cTBShared::Release(m_StringLen + 1);
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Clear() {
|
|
||||||
cTBShared::Clear();
|
|
||||||
m_StringLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Set(const cTBString &String) {
|
|
||||||
cTBShared::Set(String);
|
|
||||||
m_StringLen = String.m_StringLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Set (const char *String) {
|
|
||||||
m_StringLen = strlen(String);
|
|
||||||
Allocate(m_StringLen + 1);
|
|
||||||
|
|
||||||
memcpy(Buffer(), String, m_StringLen);
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Set (const uchar *String) {
|
|
||||||
Set((const char*)String);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Set (char Character) {
|
|
||||||
m_StringLen = 1;
|
|
||||||
Allocate(m_StringLen + 1);
|
|
||||||
|
|
||||||
Buffer()[0] = Character;
|
|
||||||
Buffer()[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Fill(char Character, int Length) {
|
|
||||||
if (Length != -1) {
|
|
||||||
m_StringLen = Length;
|
|
||||||
Allocate(m_StringLen + 1);
|
|
||||||
}
|
|
||||||
memset(Buffer(), Character, m_StringLen);
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Append(const cTBString &src) {
|
|
||||||
Allocate(m_StringLen + src.m_StringLen + 1, true);
|
|
||||||
|
|
||||||
memcpy(Buffer() + m_StringLen, src.Buffer(), src.m_StringLen);
|
|
||||||
m_StringLen += src.m_StringLen;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Append(const char *src) {
|
|
||||||
uint len = strlen(src);
|
|
||||||
Allocate(m_StringLen + len + 1, true);
|
|
||||||
|
|
||||||
memcpy(Buffer() + m_StringLen, src, len);
|
|
||||||
m_StringLen += len;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Append(char src) {
|
|
||||||
Allocate(m_StringLen + 2, true);
|
|
||||||
|
|
||||||
Buffer()[m_StringLen] = src;
|
|
||||||
++m_StringLen;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Prepend(const cTBString &src) {
|
|
||||||
Allocate(m_StringLen + src.m_StringLen + 1, true);
|
|
||||||
|
|
||||||
memmove(Buffer() + src.m_StringLen, Buffer(), m_StringLen);
|
|
||||||
memcpy(Buffer(), src.Buffer(), src.m_StringLen);
|
|
||||||
m_StringLen += src.m_StringLen;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Prepend(const char *src) {
|
|
||||||
uint len = strlen(src);
|
|
||||||
Allocate(m_StringLen + len + 1, true);
|
|
||||||
|
|
||||||
memmove(Buffer() + len, Buffer(), m_StringLen);
|
|
||||||
memcpy(Buffer(), src, len);
|
|
||||||
m_StringLen += len;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Prepend(char src) {
|
|
||||||
Allocate(m_StringLen + 2, true);
|
|
||||||
|
|
||||||
memmove(Buffer() + 1, Buffer(), m_StringLen);
|
|
||||||
Buffer()[0] = src;
|
|
||||||
Buffer()[++m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Insert(uint Index, const cTBString &String) {
|
|
||||||
Allocate(m_StringLen + String.m_StringLen + 1, true);
|
|
||||||
|
|
||||||
memmove(Buffer() + Index + String.m_StringLen, Buffer() + Index, m_StringLen - Index);
|
|
||||||
memcpy(Buffer() + Index, String.Buffer(), String.m_StringLen);
|
|
||||||
m_StringLen += String.m_StringLen;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Insert(uint Index, const char *String) {
|
|
||||||
uint len = strlen(String);
|
|
||||||
Allocate(m_StringLen + len + 1, true);
|
|
||||||
|
|
||||||
memmove(Buffer() + Index + len, Buffer() + Index, m_StringLen - Index);
|
|
||||||
memcpy(Buffer() + Index, String, len);
|
|
||||||
m_StringLen += len;
|
|
||||||
Buffer()[m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Insert(uint Index, char Character) {
|
|
||||||
Allocate(m_StringLen + 2, true);
|
|
||||||
|
|
||||||
memmove(Buffer() + Index + 1, Buffer() + Index, m_StringLen - Index);
|
|
||||||
Buffer()[Index] = Character;
|
|
||||||
Buffer()[++m_StringLen] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Left(uint count) const, ret)
|
|
||||||
if (count > m_StringLen)
|
|
||||||
count = m_StringLen;
|
|
||||||
|
|
||||||
ret.Allocate(count + 1);
|
|
||||||
memcpy(ret.Buffer(), Buffer(), count);
|
|
||||||
ret.Buffer()[count] = 0;
|
|
||||||
ret.m_StringLen = count;
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Right(uint count) const, ret)
|
|
||||||
if (count > m_StringLen)
|
|
||||||
count = m_StringLen;
|
|
||||||
|
|
||||||
ret.Allocate(count + 1);
|
|
||||||
memcpy(ret.Buffer(), Buffer() + m_StringLen - count, count);
|
|
||||||
ret.Buffer()[count] = 0;
|
|
||||||
ret.m_StringLen = count;
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Mid(int idx, int count) const, ret)
|
|
||||||
if (idx < 0)
|
|
||||||
idx = m_StringLen + idx;
|
|
||||||
|
|
||||||
if ((count < 0) || (count > (int)m_StringLen - idx))
|
|
||||||
count = m_StringLen - idx;
|
|
||||||
|
|
||||||
ret.Allocate(count + 1);
|
|
||||||
memcpy(ret.Buffer(), Buffer() + idx, count);
|
|
||||||
ret.Buffer()[count] = 0;
|
|
||||||
ret.m_StringLen = count;
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
int cTBString::Find (const cTBString &String, uint Offset) const {
|
|
||||||
if (Offset >= m_StringLen)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
char *pos = strstr(Buffer() + Offset, String.Buffer());
|
|
||||||
if (pos) return (pos - Buffer());
|
|
||||||
else return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cTBString::Find (const char *String, uint Offset) const {
|
|
||||||
if (Offset >= m_StringLen)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
char *pos = strstr(Buffer() + Offset, String);
|
|
||||||
if (pos) return (pos - Buffer());
|
|
||||||
else return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cTBString::Find (char Character, uint Offset) const {
|
|
||||||
if (Offset >= m_StringLen)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
char *pos = strchr(Buffer() + Offset, Character);
|
|
||||||
if (pos) return (pos - Buffer());
|
|
||||||
else return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TOOLBOX_REGEX
|
|
||||||
bool cTBString::Find (cTBRegEx &Regex, uint Offset) const {
|
|
||||||
return Regex.Match(Buffer(), Offset);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void cTBString::Format (const char *fmt, ...) {
|
|
||||||
int n, size = 128;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
char *buf = Buffer(size);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
va_start(ap, fmt);
|
|
||||||
n = vsnprintf(buf, size, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if ((n > -1) && (n < size))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (n > -1)
|
|
||||||
size = n + 1;
|
|
||||||
else
|
|
||||||
size *= 2;
|
|
||||||
|
|
||||||
buf = Buffer(size);
|
|
||||||
}
|
|
||||||
Release(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cTBString::Format(const cTBString &fmt, ...) {
|
|
||||||
int n, size = 128;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
char *buf = Buffer(size);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
va_start(ap, &fmt);
|
|
||||||
n = vsnprintf(buf, size, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if ((n > -1) && (n < size))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (n > -1)
|
|
||||||
size = n + 1;
|
|
||||||
else
|
|
||||||
size *= 2;
|
|
||||||
|
|
||||||
buf = Buffer(size);
|
|
||||||
}
|
|
||||||
Release(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<cTBString::TOFUNC F>
|
|
||||||
cTBString cTBString::ToAnything(void) const {
|
|
||||||
const char *src;
|
|
||||||
char *dest;
|
|
||||||
cTBString ret;
|
|
||||||
|
|
||||||
src = Buffer();
|
|
||||||
dest = ret.Buffer(m_StringLen + 1);
|
|
||||||
|
|
||||||
for (; src < Buffer() + m_StringLen; ++src, ++dest)
|
|
||||||
*dest = F(*src);
|
|
||||||
|
|
||||||
*dest = '\0';
|
|
||||||
|
|
||||||
ret.Release(m_StringLen);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<cTBString::ISFUNC F>
|
|
||||||
bool cTBString::IsAnything(void) const {
|
|
||||||
const char *ptr = Buffer();
|
|
||||||
|
|
||||||
for (; ptr < Buffer() + m_StringLen; ++ptr)
|
|
||||||
if (!F(*ptr)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
short cTBString::ToShort(bool *Ok) const {
|
|
||||||
long ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
ret = strtol(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && ret >= SHRT_MIN && ret <= SHRT_MAX)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (short)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ushort cTBString::ToUShort(bool *Ok) const {
|
|
||||||
ulong ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
ret = strtoul(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && ret <= USHRT_MAX)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (ushort)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cTBString::ToInt(bool *Ok) const {
|
|
||||||
long ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
ret = strtol(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && ret >= INT_MIN && ret <= INT_MAX)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (int)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint cTBString::ToUInt(bool *Ok) const {
|
|
||||||
ulong ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
ret = strtoul(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && ret <= UINT_MAX)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (uint)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
long cTBString::ToLong(bool *Ok) const {
|
|
||||||
long ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
ret = strtol(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && errno != ERANGE)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (long)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong cTBString::ToULong(bool *Ok) const {
|
|
||||||
ulong ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
ret = strtoul(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && errno != ERANGE)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (ulong)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
float cTBString::ToFloat(bool *Ok) const {
|
|
||||||
double ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
ret = strtod(Buffer(), &endptr);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && errno != ERANGE)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (float)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
double cTBString::ToDouble(bool *Ok) const {
|
|
||||||
double ret;
|
|
||||||
char *endptr;
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
ret = strtol(Buffer(), &endptr, 0);
|
|
||||||
|
|
||||||
if (!IsEmpty() && *endptr == '\0' && errno != ERANGE)
|
|
||||||
res = true;
|
|
||||||
|
|
||||||
if (Ok) *Ok = res;
|
|
||||||
return (double)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(short Num), ret)
|
|
||||||
ret.Format("%hd", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(ushort Num), ret)
|
|
||||||
ret.Format("%hu", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(int Num), ret)
|
|
||||||
ret.Format("%d", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(uint Num), ret)
|
|
||||||
ret.Format("%u", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(long Num), ret)
|
|
||||||
ret.Format("%ld", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(ulong Num), ret)
|
|
||||||
ret.Format("%lu", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(float Num), ret)
|
|
||||||
ret.Format("%f", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
RETURNS(cTBString, cTBString::Number(double Num), ret)
|
|
||||||
ret.Format("%f", Num);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
353
tools/string.h
353
tools/string.h
@ -1,353 +0,0 @@
|
|||||||
#ifndef TOOLBOX_STRING_H
|
|
||||||
#define TOOLBOX_STRING_H
|
|
||||||
|
|
||||||
#include "tools/tools.h"
|
|
||||||
#include "tools/shared.h"
|
|
||||||
//#include "tools/source.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef TOOLBOX_REGEX
|
|
||||||
class cTBRegEx;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class cTBString: public cTBShared {
|
|
||||||
private:
|
|
||||||
uint m_StringLen;
|
|
||||||
|
|
||||||
/* Unhide and forbid baseclass method */
|
|
||||||
virtual void Set (const cTBShared &src) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
cTBString ();
|
|
||||||
cTBString (const cTBString &src);
|
|
||||||
cTBString (const uchar *src);
|
|
||||||
cTBString (const char *src);
|
|
||||||
cTBString (char src);
|
|
||||||
virtual ~cTBString ();
|
|
||||||
|
|
||||||
static const cTBString Null;
|
|
||||||
|
|
||||||
void Clear ();
|
|
||||||
void Set (const cTBString &String);
|
|
||||||
void Set (const uchar *String);
|
|
||||||
void Set (const char *String);
|
|
||||||
void Set (char Character);
|
|
||||||
|
|
||||||
void Fill (char Character, int Length = -1);
|
|
||||||
|
|
||||||
void Release (uint newsize);
|
|
||||||
|
|
||||||
cTBString &operator= (const cTBString &src) { Set(src); return *this; }
|
|
||||||
cTBString &operator= (const char *src) { Set(src); return *this; }
|
|
||||||
cTBString &operator= (char src) { Set(src); return *this; }
|
|
||||||
|
|
||||||
void Append (const cTBString &src);
|
|
||||||
void Append (const char *src);
|
|
||||||
void Append (char src);
|
|
||||||
|
|
||||||
friend cTBString operator+ (const cTBString &a, const cTBString &b);
|
|
||||||
friend cTBString operator+ (const cTBString &a, const char *b);
|
|
||||||
friend cTBString operator+ (const char *a, const cTBString &b);
|
|
||||||
friend cTBString operator+ (const cTBString &a, char b);
|
|
||||||
friend cTBString operator+ (char a, const cTBString &b);
|
|
||||||
|
|
||||||
friend cTBString &operator+= (cTBString &a, const cTBString &b);
|
|
||||||
friend cTBString &operator+= (cTBString &a, const char *b);
|
|
||||||
friend cTBString &operator+= (cTBString &a, char b);
|
|
||||||
|
|
||||||
void Prepend (const cTBString &src);
|
|
||||||
void Prepend (const char *src);
|
|
||||||
void Prepend (char src);
|
|
||||||
|
|
||||||
void Insert (uint Index, const cTBString &src);
|
|
||||||
void Insert (uint Index, const char *src);
|
|
||||||
void Insert (uint Index, char src);
|
|
||||||
|
|
||||||
char At (uint i) const;
|
|
||||||
char operator[] (int i) const { return At((uint)i); }
|
|
||||||
|
|
||||||
char &At (uint i);
|
|
||||||
char &operator[] (int i) { return At(i); }
|
|
||||||
|
|
||||||
cTBString Left (uint Count) const;
|
|
||||||
cTBString Right (uint Count) const;
|
|
||||||
cTBString Mid (int idx, int Count = -1) const;
|
|
||||||
|
|
||||||
int Find (const cTBString &String, uint Offset = 0) const;
|
|
||||||
int Find (const char *String, uint Offset = 0) const;
|
|
||||||
int Find (char Character, uint Offset = 0) const;
|
|
||||||
#ifdef TOOLBOX_REGEX
|
|
||||||
bool Find (cTBRegEx &Regex, uint Offset = 0) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Format (const char *fmt, ...)
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
__attribute__ ((format (printf, 2, 3)))
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
void Format (const cTBString &fmt, ...);
|
|
||||||
|
|
||||||
typedef int(*TOFUNC)(int);
|
|
||||||
template<TOFUNC F> cTBString ToAnything(void) const;
|
|
||||||
|
|
||||||
cTBString ToUpper (void) const { return ToAnything<toupper>(); }
|
|
||||||
cTBString ToLower (void) const { return ToAnything<tolower>(); }
|
|
||||||
|
|
||||||
typedef int(*ISFUNC)(int);
|
|
||||||
template<ISFUNC F> bool IsAnything(void) const;
|
|
||||||
|
|
||||||
bool IsAlnum(void) const { return IsAnything<isalnum>(); }
|
|
||||||
bool IsAlpha(void) const { return IsAnything<isalpha>(); }
|
|
||||||
bool IsAscii(void) const { return IsAnything<isascii>(); }
|
|
||||||
bool IsCntrl(void) const { return IsAnything<iscntrl>(); }
|
|
||||||
bool IsDigit(void) const { return IsAnything<isdigit>(); }
|
|
||||||
bool IsGraph(void) const { return IsAnything<isgraph>(); }
|
|
||||||
bool IsLower(void) const { return IsAnything<islower>(); }
|
|
||||||
bool IsPrint(void) const { return IsAnything<isprint>(); }
|
|
||||||
bool IsPunct(void) const { return IsAnything<ispunct>(); }
|
|
||||||
bool IsSpace(void) const { return IsAnything<isspace>(); }
|
|
||||||
bool IsUpper(void) const { return IsAnything<isupper>(); }
|
|
||||||
bool IsXdigit(void) const { return IsAnything<isxdigit>(); }
|
|
||||||
|
|
||||||
#if defined(_GNU_SOURCE)
|
|
||||||
bool IsBlank(void) const { return IsAnything<isblank>(); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint Length (void) const { return m_StringLen; }
|
|
||||||
bool IsEmpty (void) const { return m_StringLen == 0; }
|
|
||||||
bool IsNull (void) const { return Buffer() == 0; }
|
|
||||||
|
|
||||||
short ToShort(bool *Ok = NULL) const;
|
|
||||||
ushort ToUShort(bool *Ok = NULL) const;
|
|
||||||
int ToInt(bool *Ok = NULL) const;
|
|
||||||
uint ToUInt(bool *Ok = NULL) const;
|
|
||||||
long ToLong(bool *Ok = NULL) const;
|
|
||||||
ulong ToULong(bool *Ok = NULL) const;
|
|
||||||
float ToFloat(bool *Ok = NULL) const;
|
|
||||||
double ToDouble(bool *Ok = NULL) const;
|
|
||||||
|
|
||||||
static cTBString Number(short Num);
|
|
||||||
static cTBString Number(ushort Num);
|
|
||||||
static cTBString Number(int Num);
|
|
||||||
static cTBString Number(uint Num);
|
|
||||||
static cTBString Number(long Num);
|
|
||||||
static cTBString Number(ulong Num);
|
|
||||||
static cTBString Number(float Num);
|
|
||||||
static cTBString Number(double Num);
|
|
||||||
|
|
||||||
friend bool operator== (const cTBString &str1, const cTBString &str2);
|
|
||||||
friend bool operator== (const cTBString &str1, const char *str2);
|
|
||||||
friend bool operator== (const char *str1, const cTBString &str2);
|
|
||||||
|
|
||||||
friend bool operator!= (const cTBString &str1, const cTBString &str2);
|
|
||||||
friend bool operator!= (const cTBString &str1, const char *str2);
|
|
||||||
friend bool operator!= (const char *str1, const cTBString &str2);
|
|
||||||
|
|
||||||
friend bool operator< (const cTBString &str1, const cTBString &str2);
|
|
||||||
friend bool operator< (const cTBString &str1, const char *str2);
|
|
||||||
friend bool operator< (const char *str1, const cTBString &str2);
|
|
||||||
|
|
||||||
friend bool operator> (const cTBString &str1, const cTBString &str2);
|
|
||||||
friend bool operator> (const cTBString &str1, const char *str2);
|
|
||||||
friend bool operator> (const char *str1, const cTBString &str2);
|
|
||||||
|
|
||||||
friend bool operator<= (const cTBString &str1, const cTBString &str2);
|
|
||||||
friend bool operator<= (const cTBString &str1, const char *str2);
|
|
||||||
friend bool operator<= (const char *str1, const cTBString &str2);
|
|
||||||
|
|
||||||
friend bool operator>= (const cTBString &str1, const cTBString &str2);
|
|
||||||
friend bool operator>= (const cTBString &str1, const char *str2);
|
|
||||||
friend bool operator>= (const char *str1, const cTBString &str2);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline char cTBString::At(uint idx) const {
|
|
||||||
ASSERT(idx >= m_StringLen);
|
|
||||||
return Buffer() ? Buffer()[idx] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char &cTBString::At(uint idx) {
|
|
||||||
static char null = 0;
|
|
||||||
ASSERT(idx >= m_StringLen);
|
|
||||||
if (Buffer()) {
|
|
||||||
Exclusive();
|
|
||||||
return Buffer()[idx];
|
|
||||||
} else
|
|
||||||
return (null = 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
RETURNS(cTBString, operator+(const cTBString &a, const cTBString &b), ret(a))
|
|
||||||
ret.Append(b);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
inline
|
|
||||||
RETURNS(cTBString, operator+ (const cTBString &a, const char *b), ret(a))
|
|
||||||
ret.Append(b);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
inline
|
|
||||||
RETURNS(cTBString, operator+ (const char *a, const cTBString &b), ret(a))
|
|
||||||
ret.Append(b);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
inline
|
|
||||||
RETURNS(cTBString, operator+ (const cTBString &a, char b), ret(a))
|
|
||||||
ret.Append(b);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
inline
|
|
||||||
RETURNS(cTBString, operator+ (char a, const cTBString &b), ret(a))
|
|
||||||
ret.Append(b);
|
|
||||||
RETURN(ret)
|
|
||||||
|
|
||||||
inline cTBString &operator+= (cTBString &a, const cTBString &b) {
|
|
||||||
a.Append(b);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cTBString &operator+= (cTBString &a, const char *b) {
|
|
||||||
a.Append(b);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cTBString &operator+= (cTBString &a, char b) {
|
|
||||||
a.Append(b);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator== (const cTBString &str1, const cTBString &str2) {
|
|
||||||
if (str1.Length() != str2.Length())
|
|
||||||
return false;
|
|
||||||
return memcmp(str1.Buffer(), str2.Buffer(), str1.Length()) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator== (const cTBString &str1, const char *str2) {
|
|
||||||
uint len = strlen(str2);
|
|
||||||
if (str1.Length() != len)
|
|
||||||
return false;
|
|
||||||
return memcmp(str1.Buffer(), str2, len) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator== (const char *str1, const cTBString &str2) {
|
|
||||||
uint len = strlen(str1);
|
|
||||||
if (len != str2.Length())
|
|
||||||
return false;
|
|
||||||
return memcmp(str1, str2.Buffer(), len) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!= (const cTBString &str1, const cTBString &str2) {
|
|
||||||
if (str1.Length() != str2.Length())
|
|
||||||
return true;
|
|
||||||
return memcmp(str1.Buffer(), str2.Buffer(), str1.Length()) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!= (const cTBString &str1, const char *str2) {
|
|
||||||
uint len = strlen(str2);
|
|
||||||
if (str1.Length() != len)
|
|
||||||
return true;
|
|
||||||
return memcmp(str1.Buffer(), str2, len) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!= (const char *str1, const cTBString &str2) {
|
|
||||||
uint len = strlen(str1);
|
|
||||||
if (len != str2.Length())
|
|
||||||
return true;
|
|
||||||
return memcmp(str1, str2.Buffer(), len) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator< (const cTBString &str1, const cTBString &str2) {
|
|
||||||
int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length());
|
|
||||||
if ((ret < 0) || ((ret == 0) && (str1.Length() < str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator< (const cTBString &str1, const char *str2) {
|
|
||||||
uint len = strlen(str2);
|
|
||||||
int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len);
|
|
||||||
if ((ret < 0) || ((ret == 0) && (str1.Length() < len)))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator< (const char *str1, const cTBString &str2) {
|
|
||||||
uint len = strlen(str1);
|
|
||||||
int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length());
|
|
||||||
if ((ret < 0) || ((ret == 0) && (len < str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator> (const cTBString &str1, const cTBString &str2) {
|
|
||||||
int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length());
|
|
||||||
if ((ret > 0) || ((ret == 0) && (str1.Length() < str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator> (const cTBString &str1, const char *str2) {
|
|
||||||
uint len = strlen(str2);
|
|
||||||
int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len);
|
|
||||||
if ((ret > 0) || ((ret == 0) && (str1.Length() < len)))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator> (const char *str1, const cTBString &str2) {
|
|
||||||
uint len = strlen(str1);
|
|
||||||
int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length());
|
|
||||||
if ((ret > 0) || ((ret == 0) && (len < str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<= (const cTBString &str1, const cTBString &str2) {
|
|
||||||
int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length());
|
|
||||||
if ((ret < 0) || ((ret == 0) && (str1.Length() <= str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<= (const cTBString &str1, const char *str2) {
|
|
||||||
uint len = strlen(str2);
|
|
||||||
int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len);
|
|
||||||
if ((ret < 0) || ((ret == 0) && (str1.Length() <= len)))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<= (const char *str1, const cTBString &str2) {
|
|
||||||
uint len = strlen(str1);
|
|
||||||
int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length());
|
|
||||||
if ((ret < 0) || ((ret == 0) && (len <= str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>= (const cTBString &str1, const cTBString &str2) {
|
|
||||||
int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length());
|
|
||||||
if ((ret > 0) || ((ret == 0) && (str1.Length() >= str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>= (const cTBString &str1, const char *str2) {
|
|
||||||
uint len = strlen(str2);
|
|
||||||
int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len);
|
|
||||||
if ((ret > 0) || ((ret == 0) && (str1.Length() >= len)))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>= (const char *str1, const cTBString &str2) {
|
|
||||||
uint len = strlen(str1);
|
|
||||||
int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length());
|
|
||||||
if ((ret > 0) || ((ret == 0) && (len >= str2.Length())))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TOOLBOX_STRING_H
|
|
Loading…
Reference in New Issue
Block a user