//  ==========================================================================
//  
//  @(#) $Id: SS7_Codec.C,v 1.3 2000/10/13 15:45:51 brian Exp $
//  
//  --------------------------------------------------------------------------
//  
//  Copyright (C) 1997-2000  Brian Bidulock <bidulock@dallas.net>
//  
//  All Rights Reserved.
//  
//  This library is free software; you can redistribute it and/or modify it
//  under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation; either version 2.1 of the License, or (at
//  your option) any later version.
//  
//  This library 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 Lesser Public License
//  for more details.
//  
//  You should have received a copy of the GNU Lesser General Public License
//  along with this library; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
//  Last Modified $Date: 2000/10/13 15:45:51 $ by $Author: brian $
// 
//  --------------------------------------------------------------------------
// 
//  $Log: SS7_Codec.C,v $
//  Revision 1.3  2000/10/13 15:45:51  brian
//  First public release.
//
//  ==========================================================================

static char const ident[] = "$Id: SS7_Codec.C,v 1.3 2000/10/13 15:45:51 brian Exp $";

#pragma implementation
#include "head.h"

#include "SS7_Codec.H"
#include <iostream.h>

Codec_NULL::Codec_NULL(char* l,char* t) :
    Parameter(l,t,0,0,0,NULL) {
};

Codec_SPAR1::Codec_SPAR1() : Field("1","Spare bit(s)",0,1) { };
Codec_SPAR2::Codec_SPAR2() : Field("2","Spare bit(s)",0,2) { };
Codec_SPAR3::Codec_SPAR3() : Field("3","Spare bit(s)",0,3) { };
Codec_SPAR4::Codec_SPAR4() : Field("4","Spare bit(s)",0,4) { };
Codec_SPAR5::Codec_SPAR5() : Field("5","Spare bit(s)",0,5) { };
Codec_SPAR6::Codec_SPAR6() : Field("6","Spare bit(s)",0,6) { };
Codec_SPAR7::Codec_SPAR7() : Field("7","Spare bit(s)",0,7) { };

Codec_PC::Codec_PC(char* l,char *t,int n,int c,int m,int x) :
    Parameter(l,t,n+m+c,3,0,(Codec**)&MEM) {
    MEM = new Field("MEM","Member",m,0);
    CLS = new Field("CLS","Cluster",c,0);
    NET = new Field("NET","Network",n,x);
    spare = x;
};

Codec_PC::Codec_PC(char* l,char* t) :
    Parameter(l,t,Codec::variant==Codec::ccitt?16:24,3,0,(Codec**)&MEM) {
    spare = Codec::variant==Codec::ccitt?2:0;
    MEM = new Field("MEM","Member", Codec::variant==Codec::ccitt?4:8,0);
    CLS = new Field("CLS","Cluster",Codec::variant==Codec::ccitt?6:8,0);
    NET = new Field("NET","Network",Codec::variant==Codec::ccitt?4:8,spare);
};

void
Codec_PC::report() {
    if (!exists&&!invalid) return;
    frame.size -= spare;
    value = (NET->value<<(MEM->size+CLS->size))|(CLS->value<<MEM->size)|MEM->value;
    Codec::report();
    if (invalid) cout.form("BAD ");
    cout.fill('0');
    cout.setf(ios::right,ios::adjustfield);
    cout.width((NET->size+2)/3); cout << NET->value; cout << '.';
    cout.width((CLS->size+2)/3); cout << CLS->value; cout << '.';
    cout.width((MEM->size+2)/3); cout << MEM->value;
    if (text) cout.form(" - %s",text);
    cout << '\n';
    Codec::morebits();
    frame.size += spare;
};

bool
Codec_PC::set(int n,int c,int m) {
    MEM->set(m);
    CLS->set(c);
    NET->set(n);
    built = true;
    return built;
};

bool
Codec_PC::get(int& n,int& c,int& m) {
    if (exists) {
        MEM->get(m);
        CLS->get(c);
        NET->get(n);
    }
    return exists;
};

bool
Codec_PC::test(int n,int c,int m) {
    if (!exists) return false;
    return (MEM->test(m)&&CLS->test(c)&&NET->test(n));
};

Codec_NAI::Codec_NAI() :
    Set("NAI","Nature of Address Ind",7,0,
        "SN",   1,   "Subscriber number (unique)",
        "RESN", 2,   "Reserved",
        "NSN",  3,   "National significant number (unique)",
        "IN",   4,   "International number (unique)",
        "AN",   5,   "Abbreviated number",
        "NUSN", 113, "Subscriber number (non-unique, op req)",
        "NIN",  114, "National significant number (non-unique, op req)",
        "NUIN", 115, "International number (non-unique, op req)",
        "NO",   116, "No number present (operator required)",
        "CTC",  117, "Cut through call to carrier",
        "950",  118, "950+ call",
        "TLTC", 119, "Test line test code",
        NULL) {
};

Codec_OE::Codec_OE() :
    Set("OE","Odd/Even Indicator",1,0,
        "EVEN", 0,  "Even",
        "ODD",  1,  "Odd",
        NULL) {
};

Codec_NPLAN::Codec_NPLAN() :
    Set("NPLAN","Numbering Plan",3,0,
        "UNK",  0,  "Unknown or not applicable",
        "ISDN", 1,  "ISDN/Telephony numbering (E.163,4)",
        "DATA", 2,  "Data numbering (X.121)",
        "TELEX",3,  "Telex numbering (F.69)",
        "MAR",  4,  "Maritime mobile numbering (E.210,1)",
        "LAND", 5,  "Land mobile or Private numbering (E.212)",
        "ISMOB",6,  "ISDN/Mobile numbering (E.214)",
        NULL) {
};

Codec_ADDI::Codec_ADDI() :
    DigitString("ADDI","Address Information",-1) {
};

Codec_SSN::Codec_SSN(char* l,char* t) :
    Set(l,t,8,0,
        "UNK",  0,  "SSN not known/not used",
        "SCMG", 1,  "SCCP Management",
        "CCITT",2,  "Reserved for CCITT allocation",
        "ISUP", 3,  "ISDN User Part",
        "OA&M", 4,  "OA&M Application Part",
        "MAP",  5,  "Mobile Application Part",
        "HLR",  6,  "Home Location Register",
        "VLR",  7,  "Visitor Location Register",
        "MSC",  8,  "Mobile Switching Center",
        "EIR",  9,  "Equipment Identifier Centre",
        "AUC",  10, "Authentication Centre",
        "OGCMS",250,"1 Way Outgoing CMS",
        "CMS",  251,"CMS/Class Services",
        "BNS",  252,"LIDB/BNS or PVN Query",
        "ACCS", 253,"LIDB/ACCS Query",
        "8XX",  254,"8XX Number Translation",
        "RES",  255,"Reserved",
        NULL) {
};

Codec_CPA::Codec_CPA(char* l,char* t) :
    Parameter(l,t,-1,8,17,(Codec**)&PCI) {
    
    TT   = new Field("TT","Translation Type",8,0);
    ES   = new Set("ES","Encoding Scheme",4,0,
        "UNK",  0,  "Unknown",
        "BCDO", 1,  "BCD, odd",
        "BCDE", 2,  "BCD, even",
        NULL);
    NPLAN= new Codec_NPLAN(); NPLAN->size = 4;
    NAI  = new Codec_NAI();
    NAI0 = new Codec_SPAR1();
    OE   = new Codec_OE();
    ADDI = new Codec_ADDI();
    
    
    SSN  = new Codec_SSN("SSN","Subsystem Number");
    SPC  = new Codec_PC("SPC","Signalling Point Code");
    GT0  = new ParameterG("GT0","No Global Title",        NULL);
    GT1  = new ParameterG("GT1","Global Title Type 0001", NAI,OE,ADDI,NULL);
    GT2  = new ParameterG("GT2","Global Title Type 0010", TT,ADDI,NULL);
    GT3  = new ParameterG("GT3","Global Title Type 0011", TT,ES,NPLAN,ADDI,NULL);
    GT4  = new ParameterG("GT4","Global Title Type 0100", TT,ES,NPLAN,NAI,NAI0,ADDI,NULL);
    GTX  = new ParameterG("GTX","Unknown Glob Titl Type", ADDI,NULL);
    
    PCI  = new Field("PCI","Point Code Indicator",1,0);
    SSNI = new Field("SSNI","Subsystem Number Ind",1,0);
    GTI  = new Field("GTI","Global Title Indicator",4,0);
    RI   = new Set("RI","Routing Indicator",1,0,
        "GT",   0,  "Route on GT",
        "DPC",  1,  "Route on DPC/SSN",
        NULL);
    NII  = new Set("NII","National/Internat Ind",1,0,
        "NAT",  0,  "National Address",
        "INT",  1,  "International Address",
        NULL);
    
    NOSPC = new Codec_NULL("NOSPC","No Signalng Point Code");
    PCI_B = new Bra("PCI","Signalling Point Code Indicator",(Codec*)PCI,
            NOSPC, 0, SPC  , 1,
        NULL);
    NOSSN = new Codec_NULL("NOSSN","No Subsystem Number");
    SSNI_B = new Bra("SSNI","Subsystem Number Indicator",(Codec*)SSNI,
            NOSSN, 0, SSN  , 1,
        NULL);
    GTI_B = new Bra("GTI","Global Title Indicator",(Codec*)GTI,
            GT0, 0, GT1, 1, GT2, 2, GT3, 3, GT4, 4, GTX,-1,
        NULL);
};


Codec_UREC::Codec_UREC(char* l,char* t) :
    Parameter(l,t,-1,1,0,(Codec**)&UREC) {
    UREC = new OctetString(l,t,-1);
};

Codec_OPARM::Codec_OPARM(char* l,char* t,Codec** a) :
    ParameterPNL(l,t,-1,4,0,(Codec**)&PTR) {
    PTR    = (Field*)a[0];
    PNAM   = (Field*)a[1];
    PL     = (Field*)a[2];
    PNAM_B = (Bra*  )a[3];
};

Codec_OPARM::Codec_OPARM(const Codec_OPARM& original) :
    ParameterPNL((ParameterPNL&)original) {
    PTR    = new Field(*original.PTR   );
    PNAM   = new Field(*original.PNAM  );
    PL     = new Field(*original.PL    );
    PNAM_B = new Bra  (*original.PNAM_B);
    PNAM_B->branch = PNAM;
    content = (Codec**)&PTR;
};

Codec_OPARM*
Codec_OPARM::copy() {
    return new Codec_OPARM(*this);
};


