403 | | * '''Description:''' in a frame library which will be based on an extension of the archive concept. The saving archive concept allows to save serializable data at the end of the archive, and the loading archive concept allows to read serializable data from the beginning of the archive. The saving frame concept will allows to save serializable data either at the end or the '''begin''' of the frame, and the loading frame concept allows to read serializable data from the beginning or the '''end''' of the archive. |
| 403 | * '''Description:''' Library based on an extension of the Archive concept making it bidirectional. |
| 404 | |
| 405 | From wikipedia "A frame is a data packet of fixed or variable length which has been encoded by a data link layer communications protocol for digital transmission over a node-to-node link. Each frame consists of a header frame synchronization and perhaps bit synchronization, payload (useful information, or a packet at higher protocol layer) and trailer. Examples are Ethernet frames and Point-to-point protocol (PPP) frames." |
| 406 | |
| 407 | The Boost.serialization saving archive concept allows to save serializable data at the end of the archive, and the loading archive concept allows to read serializable data from the beginning of the archive. |
| 408 | The saving frame concept will allows to save serializable data either at the end or the '''begin''' of the frame, and the loading frame concept allows to read serializable data from the beginning or the end of the archive. |
| 409 | |
| 410 | I'm not sure which syntax will be the more appropriated. The serialization library use the <<, >>, and & operators that are associative from left to right. We need the equivalent operators from right to left. <<=, >>=, and &= seams to be the more natural candidates but I don't know if it is correct in C++ to define this operators with this prototype |
| 411 | |
| 412 | {{{ |
| 413 | #!cpp |
| 414 | template <typename T> frame& operator<<=(const T&, frame&); |
| 415 | template <typename T> frame& operator>>=(const T&, frame&); |
| 416 | template <typename T> frame& operator&=(const T&, frame&); |
| 417 | }}} |
| 418 | |
| 419 | {{{ |
| 420 | #!cpp |
| 421 | h1 >>= h2 >>= sf << t2 << t1 |
| 422 | }}} |
| 423 | |
| 424 | is equivalent to |
| 425 | |
| 426 | {{{ |
| 427 | #!cpp |
| 428 | (h1 >>= (h2 >>= ((sf << t2) << t1))) |
| 429 | }}} |
| 430 | |
| 431 | and should be equivalent to |
| 432 | |
| 433 | {{{ |
| 434 | #!cpp |
| 435 | sa & h1 & h2 & t2 & t1 |
| 436 | }}} |
| 437 | |
| 438 | if sf and sa were empty. |
| 439 | |
| 440 | The main difference is that we can do it hierarchically. The top layer will create a frame, and serialize its own information elements. |
| 441 | |
| 442 | {{{ |
| 443 | #!cpp |
| 444 | frame sf; |
| 445 | h_n >>= sf << p_n << t_n; |
| 446 | }}} |
| 447 | |
| 448 | Then this top layer will use a primitive of the lower level having as parameter the frame as payload. |
| 449 | {{{ |
| 450 | #!cpp |
| 451 | primitive_n-1(sf); |
| 452 | }}} |
| 453 | |
| 454 | A primitive at the k level will add its own header and trailer information element to the payload of the upper level |
| 455 | |
| 456 | {{{ |
| 457 | #!cpp |
| 458 | void primitive_k(frame& sf) { |
| 459 | // ... |
| 460 | h_k >>= sf << t_k; |
| 461 | // ... |
| 462 | another_primitive_k_1(sf); |
| 463 | // ... |
| 464 | } |
| 465 | }}} |
| 466 | |
| 467 | So the frame allows to serialize top-down. To get the same result with the archive concept the serialization must be done bottom-up, needing to chain each one of the information element in a list and only when we have all off them we can start the serialization. |
| 468 | I think that the frame approach should be more efficient because it avoid to store in dynamic memory the information elements to be serialized, instead they are serialized directly. |
| 469 | |
| 470 | Loading a frame works as loading an archive, except that we can load also at the end of the frame. This avoids to load the complete archive to load the trailer of the lower levels. |
| 471 | |
| 472 | {{{ |
| 473 | #!cpp |
| 474 | lf >>= h_1; |
| 475 | // ... |
| 476 | t_1 << lf; |
| 477 | }}} |
| 478 | |
| 479 | In addition, it would be great to have saving/loading frames (I'm not sure but I think that an archive can not be saving and loading at the same time). The same frame can be used as loading, analyzing only some lower levels, and as saving in order to construct other lower levels. This will be very useful for gateways and routers. |
| 480 | |
| 481 | {{{ |
| 482 | | L4 |<------------------------------>| L4 | |
| 483 | | L3 | | ADAPTATION | | L3 | |
| 484 | | L2 |<-->| L2 | | X2 | <--> | X2 | |
| 485 | | L1 |<-->| L1 | | X1 | <--> | X1 | |
| 486 | }}} |
| 487 | |
| 488 | It would be great also that the same data that can be serialized on archives, could be serializable on a frame using the same save function. But this works only when we save at the end of the frame. Let me see this using a |
| 489 | little example: Class C has 3 information elements to serialize (a, b and c). So the save |
| 490 | functions could be something like |
| 491 | |
| 492 | {{{ |
| 493 | #!cpp |
| 494 | template <typename ARCHIVE> |
| 495 | void C::save(ARCHIVE& sa) { |
| 496 | sa & a & b & c; |
| 497 | } |
| 498 | }}} |
| 499 | |
| 500 | This save function works well from left to right, but can not be used when saving at the beginning of a frame, because the expected result when saving at the beginning is |
| 501 | |
| 502 | || a || b || c || sa || |
| 503 | |
| 504 | but the result will be |
| 505 | |
| 506 | || c || b || a || sa || |
| 507 | |
| 508 | So unfortunately we need a different save function |
| 509 | |
| 510 | {{{ |
| 511 | #!cpp |
| 512 | template <typename FRAME> |
| 513 | void C::save(FRAME& sa, begin_tag&) { |
| 514 | a >>= b >>= c >>= sa; |
| 515 | // a >>= (b >>= (c >>= sa)); |
| 516 | } |
| 517 | }}} |