arca.c

This example code encodes and decodes the ARCA binary feed.

00001 // $Id: arca_8c-example.html,v 1.2 2006/02/09 19:12:40 Daniel.May Exp $
00002 //
00003 // FIX Adapted for STreaming (sm) (FAST Protocol (sm)) 
00004 //
00005 // Copyright (c) 2005-2006, Pantor Engineering AB (http://www.pantor.com)
00006 // Copyright (c) 2005-2006, SpryWare LLC (http://www.spryware.com)
00007 // Copyright (c) 2005-2006, FIX Protocol Ltd (http://www.fixprotocol.org)
00008 // All Rights Reserved.
00009 //
00010 // This work is distributed under the W3C® Software License [1] in the
00011 // hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
00012 // implied warranty of MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS 
00013 // FOR A PARTICULAR PURPOSE.
00014 //
00015 // [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
00016 // [FPL's Intellectual Property details] http://www.fixprotocol.org/ip
00017 // [FAST Protocol details] http://www.fixprotocol.org/fast
00018 // [FAST Protocol credits] http://fixprotocol.org/fastcredits
00019 
00020 #include "arca.h"
00021 
00022 static fast_codec_t* arca_codec = NULL;
00023 
00024 static int cl_count  = 0;
00025 static int cl_decode = 0;
00026 
00028 
00029 static insert_order_msg* swap_insert_order_msg (void* data)
00030 {
00031    insert_order_msg* msg = (insert_order_msg*) data;
00032 
00033    swap16 (msg->size);
00034    swap32 (msg->time);
00035    swap32 (msg->seqno);
00036    swap32 (msg->order_ref);
00037    swap32 (msg->shares);
00038    swap32 (msg->price);
00039 
00040    return msg;
00041 }
00042 
00043 static delete_order_msg* swap_delete_order_msg (void* data)
00044 {
00045    delete_order_msg* msg = (delete_order_msg*) data;
00046 
00047    swap16 (msg->size);
00048    swap32 (msg->time);
00049    swap32 (msg->seqno);
00050    swap32 (msg->order_ref);
00051 
00052    return msg;
00053 }
00054 
00055 static modify_order_msg* swap_modify_order_msg (void* data)
00056 {
00057    modify_order_msg* msg = (modify_order_msg*) data;
00058 
00059    swap16 (msg->size);
00060    swap32 (msg->time);
00061    swap32 (msg->seqno);
00062    swap32 (msg->order_ref);
00063    swap32 (msg->shares);
00064    swap32 (msg->price);
00065 
00066    return msg;
00067 }
00068 
00069 static imbalance_msg* swap_imbalance_msg (void* data)
00070 {
00071    imbalance_msg* msg = (imbalance_msg*) data;
00072 
00073    swap16 (msg->size);
00074    swap32 (msg->time);
00075    swap32 (msg->seqno);
00076    swap32 (msg->shares);
00077    swap32 (msg->total_imbal);
00078    swap32 (msg->market_imbal);
00079    swap32 (msg->price);
00080    swap32 (msg->auction_time);
00081 
00082    return msg;
00083 }
00085 
00086 static u32 decode_str (int tag, u8* data, int size)
00087 {
00088    fast_decode_str (arca_codec, tag, data, size);
00089    return 0;
00090 }
00091 
00092 static u32 decode_u32 (int tag)
00093 {
00094    u32 temp;
00095 
00096    fast_decode_u32 (arca_codec, tag, & temp);
00097    return temp;
00098 }
00099 
00100 static i32 decode_i32 (int tag)
00101 {
00102    i32 temp;
00103 
00104    fast_decode_i32 (arca_codec, tag, & temp);
00105    return temp;
00106 }
00107 
00108 static inline void encode_i32 (u32 tag, i32 value)
00109 {
00110    fast_encode_u32 (arca_codec, tag, value);
00111 }
00112 
00113 static inline void encode_u32 (u32 tag, u32 value)
00114 {
00115    fast_encode_u32 (arca_codec, tag, value);
00116 }
00117 
00118 static inline void encode_str (int tag, u8* data, int size)
00119 {
00120    size = (int) strnlen ((char*) data, size); // remove trailing NULLs
00121    fast_encode_str (arca_codec, tag, data, size);
00122 }
00123 
00125 
00126 static inline void encode_new_msg (u32 tag)
00127 {
00128    fast_encode_new_msg (arca_codec, tag);
00129 }
00130 
00131 static inline void encode_end_msg (u32 tag)
00132 {
00133    fast_encode_end_msg (arca_codec, tag);
00134 }
00135 
00137 
00138 static void decode_insert_order (int type)
00139 {
00140    insert_order_msg msg [1];
00141    u32 secs, msecs;
00142 
00143    memset (msg, 0, sizeof (*msg));
00144 
00145    msg->type = 'A';
00146    msg->size = sizeof (insert_order_msg) - 4;
00147 
00148    secs  = decode_u32 (TSP_SECS);
00149    msecs = decode_u32 (TSP_MSECS);
00150 
00151    msg->seqno     = decode_u32 (SEQNO);
00152    msg->order_ref = decode_u32 (ORDER_REF);
00153    msg->shares    = decode_u32 (SHARES);
00154    msg->price     = decode_u32 (PRICE);
00155    msg->scale     = decode_u32 (SCALE);
00156    msg->exch_code = decode_u32 (EXCH_CODE);
00157    msg->sys_code  = decode_u32 (SYS_CODE);
00158    msg->buy_sell  = decode_u32 (BUY_SELL);
00159 
00160    decode_str (STOCK,     STR_ARGS (msg->stock));
00161    decode_str (QUOTE_ID,  STR_ARGS (msg->quote_id));
00162 
00163    msg->time = secs * 1000 + msecs;
00164 
00165    swap_insert_order_msg (msg);
00166    write_n (arca_codec->output->fd, msg, sizeof (*msg));
00167 }
00168 
00170 
00171 static void decode_delete_order (int type)
00172 {
00173    delete_order_msg msg [1];
00174    u32 secs, msecs;
00175 
00176    memset (msg, 0, sizeof (*msg));
00177 
00178    msg->type = 'D';
00179    msg->size = sizeof (delete_order_msg) - 4;
00180 
00181    secs  = decode_u32 (TSP_SECS);
00182    msecs = decode_u32 (TSP_MSECS);
00183 
00184    msg->time = secs * 1000 + msecs;
00185 
00186    msg->seqno     = decode_u32 (SEQNO);
00187    msg->order_ref = decode_u32 (ORDER_REF);
00188    msg->exch_code = decode_u32 (EXCH_CODE);
00189    msg->sys_code  = decode_u32 (SYS_CODE);
00190    msg->buy_sell  = decode_u32 (BUY_SELL);
00191 
00192    decode_str (STOCK,     STR_ARGS (msg->stock));
00193    decode_str (QUOTE_ID,  STR_ARGS (msg->quote_id));
00194 
00195    swap_delete_order_msg (msg);
00196    write_n (arca_codec->output->fd, msg, sizeof (*msg));
00197 }
00198 
00200 
00201 static void decode_modify_order (int type)
00202 {
00203    modify_order_msg msg [1];
00204    u32 secs, msecs;
00205 
00206    memset (msg, 0, sizeof (*msg));
00207 
00208    msg->type = 'M';
00209    msg->size = sizeof (modify_order_msg) - 4;
00210 
00211    secs  = decode_u32 (TSP_SECS);
00212    msecs = decode_u32 (TSP_MSECS);
00213 
00214    msg->time = secs * 1000 + msecs;
00215 
00216    msg->seqno     = decode_u32 (SEQNO);
00217    msg->order_ref = decode_u32 (ORDER_REF);
00218    msg->shares    = decode_u32 (SHARES);
00219    msg->price     = decode_u32 (PRICE);
00220    msg->scale     = decode_u32 (SCALE);
00221    msg->exch_code = decode_u32 (EXCH_CODE);
00222    msg->sys_code  = decode_u32 (SYS_CODE);
00223    msg->buy_sell  = decode_u32 (BUY_SELL);
00224 
00225    decode_str (STOCK,     STR_ARGS (msg->stock));
00226    decode_str (QUOTE_ID,  STR_ARGS (msg->quote_id));
00227 
00228    swap_modify_order_msg (msg);
00229    write_n (arca_codec->output->fd, msg, sizeof (*msg));
00230 }
00231 
00233 
00234 static void decode_imbalance (int type)
00235 {
00236    imbalance_msg msg [1];
00237    u32 secs, msecs;
00238 
00239    memset (msg, 0, sizeof (*msg));
00240 
00241    msg->type = 'I';
00242    msg->size = sizeof (imbalance_msg) - 4;
00243 
00244    secs  = decode_u32 (TSP_SECS);
00245    msecs = decode_u32 (TSP_MSECS);
00246 
00247    msg->time = secs * 1000 + msecs;
00248 
00249    msg->seqno  = decode_u32 (SEQNO);
00250    msg->shares = decode_u32 (SHARES);
00251    
00252    msg->price     = decode_u32 (PRICE);
00253    msg->scale     = decode_u32 (SCALE);
00254 
00255    msg->exch_code = decode_u32 (EXCH_CODE);
00256    msg->sys_code  = decode_u32 (SYS_CODE);
00257 
00258    decode_str (STOCK, STR_ARGS (msg->stock));
00259 
00260    msg->market_imbal = decode_i32 (MARKET_IMBAL);
00261    msg->total_imbal  = decode_i32 (TOTAL_IMBAL);
00262 
00263    msg->auction_type = decode_u32 (AUCT_TYPE);
00264    msg->auction_time = decode_u32 (AUCT_TIME);
00265 
00266    swap_imbalance_msg (msg);
00267    write_n (arca_codec->output->fd, msg, sizeof (*msg));
00268 }
00269 
00271 
00272 static int encode_insert_order (insert_order_msg* msg)
00273 {
00274    encode_new_msg (ARCA_BASE_TID);
00275 
00276    encode_u32 (MSG_TYPE,  msg->type);
00277    encode_u32 (TSP_SECS,  msg->time / 1000);
00278    encode_u32 (TSP_MSECS, msg->time % 1000);
00279 
00280    encode_u32 (SEQNO,     msg->seqno);
00281    encode_u32 (ORDER_REF, msg->order_ref);
00282    encode_u32 (SHARES,    msg->shares);
00283    encode_u32 (PRICE,     msg->price);
00284    encode_u32 (SCALE,     msg->scale);
00285 
00286    encode_u32 (EXCH_CODE, msg->exch_code);
00287    encode_u32 (SYS_CODE,  msg->sys_code);
00288    encode_u32 (BUY_SELL,  msg->buy_sell);
00289 
00290    encode_str (STOCK,     STR_ARGS (msg->stock));
00291    encode_str (QUOTE_ID,  STR_ARGS (msg->quote_id));
00292 
00293    encode_end_msg (ARCA_BASE_TID);
00294    return 0;
00295 }
00296 
00298 
00299 static int encode_delete_order (delete_order_msg* msg)
00300 {
00301    encode_new_msg (ARCA_BASE_TID);
00302 
00303    encode_u32 (MSG_TYPE,  msg->type);
00304    encode_u32 (TSP_SECS,  msg->time / 1000);
00305    encode_u32 (TSP_MSECS, msg->time % 1000);
00306 
00307    encode_u32 (SEQNO,     msg->seqno);
00308    encode_u32 (ORDER_REF, msg->order_ref);
00309 
00310    encode_u32 (EXCH_CODE, msg->exch_code);
00311    encode_u32 (SYS_CODE,  msg->sys_code);
00312    encode_u32 (BUY_SELL,  msg->buy_sell);
00313 
00314    encode_str (STOCK,     STR_ARGS (msg->stock));
00315    encode_str (QUOTE_ID,  STR_ARGS (msg->quote_id));
00316 
00317    encode_end_msg (ARCA_BASE_TID);
00318    return 0;
00319 }
00320 
00322 
00323 static int encode_modify_order (modify_order_msg* msg)
00324 {
00325    encode_new_msg (ARCA_BASE_TID);
00326 
00327    encode_u32 (MSG_TYPE,  msg->type);
00328    encode_u32 (TSP_SECS,  msg->time / 1000);
00329    encode_u32 (TSP_MSECS, msg->time % 1000);
00330 
00331    encode_u32 (SEQNO,     msg->seqno);
00332    encode_u32 (ORDER_REF, msg->order_ref);
00333    encode_u32 (SHARES,    msg->shares);
00334    encode_u32 (PRICE,     msg->price);
00335    encode_u32 (SCALE,     msg->scale);
00336 
00337    encode_u32 (EXCH_CODE, msg->exch_code);
00338    encode_u32 (SYS_CODE,  msg->sys_code);
00339    encode_u32 (BUY_SELL,  msg->buy_sell);
00340 
00341    encode_str (STOCK,     STR_ARGS (msg->stock));
00342    encode_str (QUOTE_ID,  STR_ARGS (msg->quote_id));
00343 
00344    encode_end_msg (ARCA_BASE_TID);
00345    return 0;
00346 }
00347 
00349 
00350 static int encode_imbalance (imbalance_msg* msg)
00351 {
00352    encode_new_msg (ARCA_BASE_TID);
00353 
00354    encode_u32 (MSG_TYPE,     msg->type);
00355    encode_u32 (TSP_SECS,     msg->time / 1000);
00356    encode_u32 (TSP_MSECS,    msg->time % 1000);
00357 
00358    encode_u32 (SEQNO,        msg->seqno);
00359    encode_u32 (SHARES,       msg->shares);
00360 
00361    encode_u32 (PRICE,        msg->price);
00362    encode_u32 (SCALE,        msg->scale);
00363 
00364    encode_u32 (EXCH_CODE,    msg->exch_code);
00365    encode_u32 (SYS_CODE,     msg->sys_code);
00366 
00367    encode_str (STOCK,        STR_ARGS (msg->stock));
00368 
00369    encode_i32 (MARKET_IMBAL, msg->market_imbal);
00370    encode_i32 (TOTAL_IMBAL,  msg->total_imbal);
00371 
00372    encode_u32 (AUCT_TYPE,    msg->auction_type);
00373    encode_u32 (AUCT_TIME,    msg->auction_time);
00374 
00375    encode_end_msg (ARCA_BASE_TID);
00376    return 0;
00377 }
00378 
00380 
00381 static int arca_decoder (void)
00382 {
00383    int count;
00384 
00385    for (count = 1 ;; count ++)
00386    {
00387       u32 msg_type;
00388 
00389       if (cl_count > 0 && count > cl_count)
00390          break;
00391 
00392       if (fast_decode_new_msg (arca_codec, ARCA_BASE_TID) < 0)
00393          break;
00394 
00395       msg_type = decode_u32 (MSG_TYPE);
00396 
00397       switch (msg_type)
00398       {
00399        case 'A':
00400          decode_insert_order (msg_type);
00401          break;
00402 
00403        case 'D':
00404          decode_delete_order (msg_type);
00405          break;
00406 
00407        case 'M':
00408          decode_modify_order (msg_type);
00409          break;
00410 
00411        case 'I':
00412          decode_imbalance (msg_type);
00413          break;
00414 
00415        default:
00416          fprintf (stderr, "fatal: %02x unknown type\n", msg_type);
00417          exit (0);
00418       }
00419 
00420       if (fast_decode_end_msg (arca_codec, ARCA_BASE_TID) < 0)
00421          break;
00422    }
00423    return 0;
00424 }
00425 
00426 static int arca_encoder (void)
00427 {
00428    char data [128];
00429 
00430    int error = 0;
00431    int count;
00432 
00433    for (count = 0 ; cl_count == 0 || count < cl_count ; count ++)
00434    {
00435       char* hdr  = data;
00436       char* body = hdr + 4; // VC can't do arith on void*
00437 
00438       int length;
00439 
00440       // Read four bytes header
00441       if (read_n (arca_codec->input->fd, data, 4) < 0)
00442          return -1;
00443 
00444       length = (hdr [0] << 8) | hdr [1];
00445 
00446       assert (length <= sizeof (data) - 4);
00447 
00448       // Read the body part
00449       if (read_n (arca_codec->input->fd, body, length) < 0)
00450       {
00451          perror ("read_n: body part");
00452          break;
00453       }
00454 
00455       switch (data [2])
00456       {
00457        case 'A':
00458          encode_insert_order (swap_insert_order_msg (data));
00459          break;
00460 
00461        case 'D':
00462          encode_delete_order (swap_delete_order_msg (data));
00463          break;
00464 
00465        case 'I':
00466          encode_imbalance (swap_imbalance_msg (data));
00467          break;
00468 
00469        case 'M':
00470          encode_modify_order (swap_modify_order_msg (data));
00471          break;
00472 
00473        default:
00474          fprintf (stderr, "fatal: unknown type='%c'\n", data [2]);
00475          abort ();
00476       }
00477 
00478       if (error != 0)
00479          break;
00480    }
00481    return 0;
00482 }
00483 
00485 
00486 #define OPTS "A:c:DV?"
00487 
00488 int main (int argc, char* argv [])
00489 {
00490    init_platform_io ();
00491 
00492    arca_codec = fast_create_codec ();
00493 
00494    assert (arca_codec != NULL);
00495 
00496    for (;;)
00497    {
00498       int option = getopt (argc, argv, OPTS);
00499 
00500       if (option == EOF)
00501          break;
00502 
00503       switch (option)
00504       {
00505        case 'c':
00506          cl_count = atoi (optarg);
00507          break;
00508 
00509        case 'D':
00510          cl_decode = 1;
00511          break;
00512 
00513        case 'V':
00514          arca_codec->verbose ++;
00515          break;
00516 
00517        case '?':
00518          fprintf (stderr, "encoder [-cDV] <infile >outfile\n");
00519          exit (0);
00520 
00521        default:
00522          fprintf (stderr, "error: '%c' unknown option\n", option);
00523          exit (1);
00524       }
00525    }
00526 
00527    if (cl_decode)
00528       arca_decoder ();
00529    else
00530       arca_encoder ();
00531 
00532    exit (0);
00533 }

Generated on Thu Feb 9 13:11:32 2006 for fastapi by doxygen 1.4.6-NO    FAST ProtocolSM