📄 rvmegacoencode.c
字号:
#include "rvmegacoencode.h"
#include "rvsdpenc.h"
const char *nullStr = "";
typedef struct
{
const char *indent0, *indent1, *indent2, *indent3;
const char *comma, *comma0, *comma2, *comma3;
const char *brace0, *brace3;
} RvFormatTable;
RvFormatTable rvFormatPretty =
{
"\n", "\n\t", "\n\t\t", "\n\t\t\t",
", ", ",\n", ",\n\t\t", ",\n\t\t\t",
"{\n", "{\n\t\t\t"
};
RvFormatTable rvFormatSmall =
{
"", "", "", "",
",", ",", ",", ",",
"{", "{"
};
typedef struct
{
RvBool compact;
const RvFormatTable *format;
} RvMegacoEncodeOptions;
typedef enum
{
RV_MEGACOENCODEERROR_CORRUPTOBJECT = 1,
RV_MEGACOENCODEERROR_MISSINGPARAMETER
} RvMegacoEncodeError;
static void rvTimeStampEncode(const RvTimeStamp *x, RvStrStream *os)
{
char fill = '0';
rvStrStreamWriteUIntW(os, rvTimeStampGetYear(x), 4, fill);
rvStrStreamWriteUIntW(os, rvTimeStampGetMonth(x), 2, fill);
rvStrStreamWriteUIntW(os, rvTimeStampGetDay(x), 2, fill);
rvStrStreamPut(os, 'T');
rvStrStreamWriteUIntW(os, rvTimeStampGetHour(x), 2, fill);
rvStrStreamWriteUIntW(os, rvTimeStampGetMinute(x), 2, fill);
rvStrStreamWriteUIntW(os, rvTimeStampGetHsecs(x), 4, fill);
}
static void rvMegacoEntityAddressEncode(const RvMegacoEntityAddress *x, RvStrStream *os)
{
RvInetPort port = rvMegacoEntityAddressGetPort(x);
switch(rvMegacoEntityAddressGetType(x))
{
case RV_MEGACOENTITYADDRESSTYPE_IP:
rvStrStreamPut(os, '[');
rvStrStreamWriteStr(os, rvMegacoEntityAddressGetAddress(x));
rvStrStreamPut(os, ']');
break;
case RV_MEGACOENTITYADDRESSTYPE_DNS:
rvStrStreamPut(os, '<');
rvStrStreamWriteStr(os, rvMegacoEntityAddressGetAddress(x));
rvStrStreamPut(os, '>');
break;
case RV_MEGACOENTITYADDRESSTYPE_DEVICE:
rvStrStreamWriteStr(os, rvMegacoEntityAddressGetAddress(x));
return;
case RV_MEGACOENTITYADDRESSTYPE_MTP:
rvStrStreamWriteStr(os, "MTP{");
rvStrStreamWriteStr(os, rvMegacoEntityAddressGetAddress(x));
rvStrStreamPut(os, '}');
return;
}
if(port)
{
rvStrStreamPut(os, ':');
rvStrStreamWriteUInt(os, port);
}
}
static void rvMegacoTerminationIdEncode(const RvMegacoTerminationId *x, RvStrStream *os)
{
rvStrStreamWriteStr(os, rvMegacoTerminationIdGetId(x));
}
static void rvMegacoContextIdEncode(const RvMegacoContextId *x, RvStrStream *os)
{
switch(rvMegacoContextIdGetType(x))
{
case RV_MEGACOCONTEXTID_NORMAL:
rvStrStreamWriteUInt(os, rvMegacoContextIdGetId(x));
break;
case RV_MEGACOCONTEXTID_NULL:
rvStrStreamPut(os, '-');
break;
case RV_MEGACOCONTEXTID_CHOOSE:
rvStrStreamPut(os, '$');
break;
case RV_MEGACOCONTEXTID_ALL:
rvStrStreamPut(os, '*');
break;
default:
rvStrStreamSetErrorStatus(os, RV_MEGACOENCODEERROR_CORRUPTOBJECT);
break;
}
}
static void rvMegacoPackageItemEncode(const RvMegacoPackageItem *x, RvStrStream *os)
{
const char *pkg = rvMegacoPackageItemGetPackage(x);
if(*pkg)
{
rvStrStreamWriteStr(os, pkg);
rvStrStreamPut(os, '/');
}
rvStrStreamWriteStr(os, rvMegacoPackageItemGetItem(x));
}
static void rvMegacoParameterValueEncode(const RvMegacoParameterValue *x, RvStrStream *os)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
size_t i;
switch(rvMegacoParameterValueGetType(x))
{
case RV_RELATION_EQUAL:
rvStrStreamPut(os, '=');
rvStrStreamWriteStr(os, rvMegacoParameterValueGetValue(x));
break;
case RV_RELATION_LESS:
rvStrStreamPut(os, '<');
rvStrStreamWriteStr(os, rvMegacoParameterValueGetValue(x));
break;
case RV_RELATION_GREATER:
rvStrStreamPut(os, '>');
rvStrStreamWriteStr(os, rvMegacoParameterValueGetValue(x));
break;
case RV_RELATION_INEQUAL:
rvStrStreamPut(os, '#');
rvStrStreamWriteStr(os, rvMegacoParameterValueGetValue(x));
break;
case RV_RELATION_AND:
rvStrStreamWriteStr(os, "=[");
for(i=0; i<rvMegacoParameterValueGetListSize(x); ++i)
{
if(i) rvStrStreamWriteStr(os, opt->format->comma);
rvStrStreamWriteStr(os, rvMegacoParameterValueGetListValue(x, i));
}
rvStrStreamPut(os, ']');
break;
case RV_RELATION_OR:
rvStrStreamWriteStr(os, "={");
for(i=0; i<rvMegacoParameterValueGetListSize(x); ++i)
{
if(i) rvStrStreamWriteStr(os, opt->format->comma);
rvStrStreamWriteStr(os, rvMegacoParameterValueGetListValue(x, i));
}
rvStrStreamPut(os, '}');
break;
case RV_RELATION_RANGE:
rvStrStreamWriteStr(os, "=[");
rvStrStreamWriteStr(os, rvMegacoParameterValueGetRangeMin(x));
rvStrStreamPut(os, ':');
rvStrStreamWriteStr(os, rvMegacoParameterValueGetRangeMin(x));
rvStrStreamPut(os, ']');
break;
default:
rvStrStreamSetErrorStatus(os, RV_MEGACOENCODEERROR_CORRUPTOBJECT);
break;
}
}
static void rvMegacoParameterListEncode(const RvMegacoParameterList *x, RvStrStream *os)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
const char *sep = nullStr;
RvMapIter(RvMegacoPackageItem, RvMegacoParameterValue) iter;
for(iter = rvMapBegin(RvMegacoPackageItem, RvMegacoParameterValue)(&x->list);
iter != rvMapEnd(RvMegacoPackageItem, RvMegacoParameterValue)(&x->list);
iter = rvMapIterNext(iter))
{
rvStrStreamWriteStr(os, sep);
rvMegacoPackageItemEncode(rvMapIterGetKey(RvMegacoPackageItem, RvMegacoParameterValue)(iter), os);
rvMegacoParameterValueEncode(rvMapIterGetValue(RvMegacoPackageItem, RvMegacoParameterValue)(iter), os);
sep = opt->format->comma;
}
}
static void rvMegacoDigitPositionEncode(const RvMegacoDigitPosition *x, RvStrStream *os)
{
if(rvMegacoDigitPositionGetEvents(x) == (1 << 10) - 1)
{
rvStrStreamPut(os, 'x');
}
else
{
const char *name = "0123456789ABCDEFGHIJK";
RvBool first = rvTrue, single = rvTrue;
int val;
for(val = rvMegacoDigitPositionGetEvents(x); val; val >>= 1, ++name)
{
if(val & 1)
{
if(first)
{
first = rvFalse;
if(val & ~1)
rvStrStreamPut(os, '['), single = rvFalse;
}
rvStrStreamPut(os, *name);
/* compact ranges of 4 or more consecutive digits */
if(*name <= '6')
{
int streak = 0, i;
for(i=4; i<='9'+1-*name; ++i)
{
if(~val & (1 << i) - 1)
break;
streak = i;
}
if(streak)
{
val >>= streak-1, name += streak-1;
rvStrStreamPut(os, '-');
rvStrStreamPut(os, *name);
}
}
}
}
if(!single)
rvStrStreamPut(os, ']');
}
if(rvMegacoDigitPositionIsMultiple(x))
rvStrStreamPut(os, '.');
}
static void rvMegacoDigitStringEncode(const RvMegacoDigitString *x, RvStrStream *os)
{
size_t i;
for(i=0; i<rvMegacoDigitStringGetSize(x); ++i)
rvMegacoDigitPositionEncode(rvMegacoDigitStringGetElem(x, i), os);
}
static void rvMegacoDigitMapEncode(const RvMegacoDigitMap *x, RvStrStream *os)
{
size_t i, size = rvMegacoDigitMapGetSize(x);
if(rvMegacoDigitMapGetStartTimeout(x) != rvMegacoDigitMapDefaultStartTimeout)
{
rvStrStreamWriteStr(os, "T:");
rvStrStreamWriteUInt(os, rvMegacoDigitMapGetStartTimeout(x));
rvStrStreamPut(os, ',');
}
if(rvMegacoDigitMapGetShortTimeout(x) != rvMegacoDigitMapDefaultShortTimeout)
{
rvStrStreamWriteStr(os, "S:");
rvStrStreamWriteUInt(os, rvMegacoDigitMapGetShortTimeout(x));
rvStrStreamPut(os, ',');
}
if(rvMegacoDigitMapGetLongTimeout(x) != rvMegacoDigitMapDefaultLongTimeout)
{
rvStrStreamWriteStr(os, "L:");
rvStrStreamWriteUInt(os, rvMegacoDigitMapGetLongTimeout(x));
rvStrStreamPut(os, ',');
}
if(size > 1)
rvStrStreamPut(os, '(');
for(i=0; i<size; ++i)
{
if(i) rvStrStreamPut(os, '|');
rvMegacoDigitStringEncode(rvMegacoDigitMapGetElem(x, i), os);
}
if(size > 1)
rvStrStreamPut(os, ')');
}
static void rvMegacoDigitMapDescriptorEncode(const RvMegacoDigitMapDescriptor *x, RvStrStream *os)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
const char *name = rvMegacoDigitMapDescriptorGetName(x);
const RvMegacoDigitMap *dm = rvMegacoDigitMapDescriptorGetDigitMap(x);
size_t sz = rvMegacoDigitMapGetSize(dm);
rvStrStreamWriteStr(os, opt->compact ? "DM" : "DigitMap");
if(*name || sz)
{
rvStrStreamPut(os, '=');
rvStrStreamWriteStr(os, name);
if(sz)
{
rvStrStreamPut(os, '{');
rvMegacoDigitMapEncode(dm, os);
rvStrStreamPut(os, '}');
}
}
}
static void rvMegacoEventEncode(const RvMegacoEvent *x, RvStrStream *os)
{
unsigned int streamId = rvMegacoEventGetStreamId(x);
const RvMegacoParameterList *params = rvMegacoEventGetParameterList(x);
rvMegacoPackageItemEncode(rvMegacoEventGetName(x), os);
if(streamId || !rvMegacoParameterListIsEmpty(params))
{
rvStrStreamPut(os, '{');
if(streamId)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
rvStrStreamWriteStr(os, opt->compact ? "ST=" : "Stream=");
rvStrStreamWriteUInt(os, streamId);
rvStrStreamWriteStr(os, opt->format->comma);
}
rvMegacoParameterListEncode(params, os);
rvStrStreamPut(os, '}');
}
}
static void rvMegacoSignalEncode(const RvMegacoSignal *x, RvStrStream *os)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
unsigned int reasons = rvMegacoSignalGetNotifyReasons(x);
const RvMegacoParameterList *params = rvMegacoSignalGetParameterList(x);
const char *sep = "{";
rvMegacoPackageItemEncode(rvMegacoSignalGetName(x), os);
if(rvMegacoSignalGetStreamId(x))
{
rvStrStreamWriteStr(os, sep);
rvStrStreamWriteStr(os, opt->compact ? "ST=" : "Stream=");
rvStrStreamWriteUInt(os, rvMegacoSignalGetStreamId(x));
sep = opt->format->comma;
}
if(rvMegacoSignalGetType(x) != RV_MEGACOSIGNAL_DEFAULTTYPE)
{
rvStrStreamWriteStr(os, sep);
rvStrStreamWriteStr(os, opt->compact ? "SY=" : "SignalType=");
switch(rvMegacoSignalGetType(x))
{
case RV_MEGACOSIGNAL_ONOFF:
rvStrStreamWriteStr(os, opt->compact ? "OO" : "OnOff");
break;
case RV_MEGACOSIGNAL_TIMEOUT:
rvStrStreamWriteStr(os, opt->compact ? "TO" : "TimeOut");
if(rvMegacoSignalGetDuration(x))
{
rvStrStreamWriteStr(os, opt->format->comma);
rvStrStreamWriteStr(os, opt->compact ? "DR=" : "Duration=");
rvStrStreamWriteUInt(os, rvMegacoSignalGetDuration(x));
}
break;
case RV_MEGACOSIGNAL_BRIEF:
rvStrStreamWriteStr(os, opt->compact ? "BR" : "Brief");
break;
default:
rvStrStreamSetErrorStatus(os, RV_MEGACOENCODEERROR_CORRUPTOBJECT);
break;
}
sep = opt->format->comma;
}
if(!rvMegacoParameterListIsEmpty(params))
{
rvStrStreamWriteStr(os, sep);
rvMegacoParameterListEncode(params, os);
sep = opt->format->comma;
}
if(reasons)
{
const char *sep2 = nullStr;
rvStrStreamWriteStr(os, sep);
rvStrStreamWriteStr(os, opt->compact ? "NC={" : "NotifyCompletion={");
if(reasons & RV_MEGACOSIGNAL_COMPLETED)
{
rvStrStreamWriteStr(os, opt->compact ? "TO" : "TimeOut");
sep2 = opt->format->comma;
}
if(reasons & RV_MEGACOSIGNAL_GOTEVENT)
{
rvStrStreamWriteStr(os, sep2);
rvStrStreamWriteStr(os, opt->compact ? "IBE" : "IntByEvent");
sep2 = opt->format->comma;
}
if(reasons & RV_MEGACOSIGNAL_NEWSIGDESCR)
{
rvStrStreamWriteStr(os, sep2);
rvStrStreamWriteStr(os, opt->compact ? "IBS" : "IntBySigDescr");
sep2 = opt->format->comma;
}
if(reasons & RV_MEGACOSIGNAL_OTHERREASON)
{
rvStrStreamWriteStr(os, sep2);
rvStrStreamWriteStr(os, opt->compact ? "OR" : "OtherReason");
}
rvStrStreamPut(os, '}');
sep = opt->format->comma;
}
if(rvMegacoSignalGetKeepActiveFlag(x))
{
rvStrStreamWriteStr(os, sep);
rvStrStreamWriteStr(os, opt->compact ? "KA" : "KeepActive");
sep = opt->format->comma;
}
if(sep == opt->format->comma)
{
rvStrStreamPut(os, '}');
}
}
static void rvMegacoSignalListEncode(const RvMegacoSignalList *x, RvStrStream *os)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
size_t i;
rvStrStreamWriteStr(os, opt->compact ? "SL=" : "SignalList=");
rvStrStreamWriteUInt(os, rvMegacoSignalListGetId(x));
rvStrStreamPut(os, '{');
for(i=0; i<rvMegacoSignalListGetSize(x); ++i)
{
if(i) rvStrStreamWriteStr(os, opt->format->comma);
rvMegacoSignalEncode(rvMegacoSignalListGetElem(x, i), os);
}
rvStrStreamPut(os, '}');
}
static void rvMegacoSignalsDescriptorEncode(const RvMegacoSignalsDescriptor *x, RvStrStream *os)
{
RvMegacoEncodeOptions *opt = (RvMegacoEncodeOptions *)rvStrStreamGetUserData(os);
rvStrStreamWriteStr(os, opt->compact ? "SG" : "Signals");
if(rvMegacoSignalsDescriptorIsSet(x))
{
const char *sep = nullStr;
size_t i;
rvStrStreamPut(os, '{');
for(i=0; i<rvMegacoSignalsDescriptorGetNumSignalLists(x); ++i)
{
rvStrStreamWriteStr(os, sep);
rvMegacoSignalListEncode(rvMegacoSignalsDescriptorGetSignalList(x, i), os);
sep = opt->format->comma;
}
for(i=0; i<rvMegacoSignalsDescriptorGetNumSignals(x); ++i)
{
rvStrStreamWriteStr(os, sep);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -