diff --git a/include/satnogs/amsat_duv_decoder.h b/include/satnogs/amsat_duv_decoder.h index 0566810..ce17326 100644 --- a/include/satnogs/amsat_duv_decoder.h +++ b/include/satnogs/amsat_duv_decoder.h @@ -26,17 +26,14 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief AMSAT 8b10b + CCSDS RS DUV decoder * */ -class SATNOGS_API amsat_duv_decoder : public decoder -{ +class SATNOGS_API amsat_duv_decoder : public decoder { public: static const size_t @@ -46,20 +43,19 @@ public: amsat_fox_spacecraft_id[]; static decoder::decoder_sptr - make(const std::string& control_symbol, size_t max_frame_len = 96); + make(const std::string &control_symbol, size_t max_frame_len = 96); - amsat_duv_decoder (const std::string& control_symbol, size_t max_frame_len); - ~amsat_duv_decoder (); + amsat_duv_decoder(const std::string &control_symbol, size_t max_frame_len); + ~amsat_duv_decoder(); decoder_status_t - decode (const void *in, int len); + decode(const void *in, int len); void - reset (); + reset(); private: - typedef enum - { + typedef enum { SEARCH_SYNC, DECODING } d_state_t; @@ -80,531 +76,533 @@ private: std::deque d_bitstream; bool - set_access_code (const std::string &control_symbol); + set_access_code(const std::string &control_symbol); void - process_10b (uint16_t word, size_t write_pos); + process_10b(uint16_t word, size_t write_pos); inline uint16_t pack_10b_word(size_t idx); - int d_lookup_8b10b[2][256] = - { + int d_lookup_8b10b[2][256] = { // RD = -1 cases - { - /* 00 */0x274, - /* 01 */0x1d4, - /* 02 */0x2d4, - /* 03 */0x71b, - /* 04 */0x354, - /* 05 */0x69b, - /* 06 */0x59b, - /* 07 */0x78b, - /* 08 */0x394, - /* 09 */0x65b, - /* 0a */0x55b, - /* 0b */0x74b, - /* 0c */0x4db, - /* 0d */0x6cb, - /* 0e */0x5cb, - /* 0f */0x174, - /* 10 */0x1b4, - /* 11 */0x63b, - /* 12 */0x53b, - /* 13 */0x72b, - /* 14 */0x4bb, - /* 15 */0x6ab, - /* 16 */0x5ab, - /* 17 */0x3a4, - /* 18 */0x334, - /* 19 */0x66b, - /* 1a */0x56b, - /* 1b */0x364, - /* 1c */0x4eb, - /* 1d */0x2e4, - /* 1e */0x1e4, - /* 1f */0x2b4, - /* 20 */0x679, - /* 21 */0x5d9, - /* 22 */0x6d9, - /* 23 */0x319, - /* 24 */0x759, - /* 25 */0x299, - /* 26 */0x199, - /* 27 */0x389, - /* 28 */0x799, - /* 29 */0x259, - /* 2a */0x159, - /* 2b */0x349, - /* 2c */0x0d9, - /* 2d */0x2c9, - /* 2e */0x1c9, - /* 2f */0x579, - /* 30 */0x5b9, - /* 31 */0x239, - /* 32 */0x139, - /* 33 */0x329, - /* 34 */0x0b9, - /* 35 */0x2a9, - /* 36 */0x1a9, - /* 37 */0x7a9, - /* 38 */0x739, - /* 39 */0x269, - /* 3a */0x169, - /* 3b */0x769, - /* 3c */0x0e9, - /* 3d */0x6e9, - /* 3e */0x5e9, - /* 3f */0x6b9, - /* 40 */0x675, - /* 41 */0x5d5, - /* 42 */0x6d5, - /* 43 */0x315, - /* 44 */0x755, - /* 45 */0x295, - /* 46 */0x195, - /* 47 */0x385, - /* 48 */0x795, - /* 49 */0x255, - /* 4a */0x155, - /* 4b */0x345, - /* 4c */0x0d5, - /* 4d */0x2c5, - /* 4e */0x1c5, - /* 4f */0x575, - /* 50 */0x5b5, - /* 51 */0x235, - /* 52 */0x135, - /* 53 */0x325, - /* 54 */0x0b5, - /* 55 */0x2a5, - /* 56 */0x1a5, - /* 57 */0x7a5, - /* 58 */0x735, - /* 59 */0x265, - /* 5a */0x165, - /* 5b */0x765, - /* 5c */0x0e5, - /* 5d */0x6e5, - /* 5e */0x5e5, - /* 5f */0x6b5, - /* 60 */0x673, - /* 61 */0x5d3, - /* 62 */0x6d3, - /* 63 */0x31c, - /* 64 */0x753, - /* 65 */0x29c, - /* 66 */0x19c, - /* 67 */0x38c, - /* 68 */0x793, - /* 69 */0x25c, - /* 6a */0x15c, - /* 6b */0x34c, - /* 6c */0x0dc, - /* 6d */0x2cc, - /* 6e */0x1cc, - /* 6f */0x573, - /* 70 */0x5b3, - /* 71 */0x23c, - /* 72 */0x13c, - /* 73 */0x32c, - /* 74 */0x0bc, - /* 75 */0x2ac, - /* 76 */0x1ac, - /* 77 */0x7a3, - /* 78 */0x733, - /* 79 */0x26c, - /* 7a */0x16c, - /* 7b */0x763, - /* 7c */0x0ec, - /* 7d */0x6e3, - /* 7e */0x5e3, - /* 7f */0x6b3, - /* 80 */0x272, - /* 81 */0x1d2, - /* 82 */0x2d2, - /* 83 */0x71d, - /* 84 */0x352, - /* 85 */0x69d, - /* 86 */0x59d, - /* 87 */0x78d, - /* 88 */0x392, - /* 89 */0x65d, - /* 8a */0x55d, - /* 8b */0x74d, - /* 8c */0x4dd, - /* 8d */0x6cd, - /* 8e */0x5cd, - /* 8f */0x172, - /* 90 */0x1b2, - /* 91 */0x63d, - /* 92 */0x53d, - /* 93 */0x72d, - /* 94 */0x4bd, - /* 95 */0x6ad, - /* 96 */0x5ad, - /* 97 */0x3a2, - /* 98 */0x332, - /* 99 */0x66d, - /* 9a */0x56d, - /* 9b */0x362, - /* 9c */0x4ed, - /* 9d */0x2e2, - /* 9e */0x1e2, - /* 9f */0x2b2, - /* a0 */0x67a, - /* a1 */0x5da, - /* a2 */0x6da, - /* a3 */0x31a, - /* a4 */0x75a, - /* a5 */0x29a, - /* a6 */0x19a, - /* a7 */0x38a, - /* a8 */0x79a, - /* a9 */0x25a, - /* aa */0x15a, - /* ab */0x34a, - /* ac */0x0da, - /* ad */0x2ca, - /* ae */0x1ca, - /* af */0x57a, - /* b0 */0x5ba, - /* b1 */0x23a, - /* b2 */0x13a, - /* b3 */0x32a, - /* b4 */0x0ba, - /* b5 */0x2aa, - /* b6 */0x1aa, - /* b7 */0x7aa, - /* b8 */0x73a, - /* b9 */0x26a, - /* ba */0x16a, - /* bb */0x76a, - /* bc */0x0ea, - /* bd */0x6ea, - /* be */0x5ea, - /* bf */0x6ba, - /* c0 */0x676, - /* c1 */0x5d6, - /* c2 */0x6d6, - /* c3 */0x316, - /* c4 */0x756, - /* c5 */0x296, - /* c6 */0x196, - /* c7 */0x386, - /* c8 */0x796, - /* c9 */0x256, - /* ca */0x156, - /* cb */0x346, - /* cc */0x0d6, - /* cd */0x2c6, - /* ce */0x1c6, - /* cf */0x576, - /* d0 */0x5b6, - /* d1 */0x236, - /* d2 */0x136, - /* d3 */0x326, - /* d4 */0x0b6, - /* d5 */0x2a6, - /* d6 */0x1a6, - /* d7 */0x7a6, - /* d8 */0x736, - /* d9 */0x266, - /* da */0x166, - /* db */0x766, - /* dc */0x0e6, - /* dd */0x6e6, - /* de */0x5e6, - /* df */0x6b6, - /* e0 */0x271, - /* e1 */0x1d1, - /* e2 */0x2d1, - /* e3 */0x71e, - /* e4 */0x351, - /* e5 */0x69e, - /* e6 */0x59e, - /* e7 */0x78e, - /* e8 */0x391, - /* e9 */0x65e, - /* ea */0x55e, - /* eb */0x74e, - /* ec */0x4de, - /* ed */0x6ce, - /* ee */0x5ce, - /* ef */0x171, - /* f0 */0x1b1, - /* f1 */0x637, - /* f2 */0x537, - /* f3 */0x72e, - /* f4 */0x4b7, - /* f5 */0x6ae, - /* f6 */0x5ae, - /* f7 */0x3a1, - /* f8 */0x331, - /* f9 */0x66e, - /* fa */0x56e, - /* fb */0x361, - /* fc */0x4ee, - /* fd */0x2e1, - /* fe */0x1e1, - /* ff */0x2b1, }, // RD = +1 cases - { - /* 00 */0x58b, - /* 01 */0x62b, - /* 02 */0x52b, - /* 03 */0x314, - /* 04 */0x4ab, - /* 05 */0x294, - /* 06 */0x194, - /* 07 */0x074, - /* 08 */0x46b, - /* 09 */0x254, - /* 0a */0x154, - /* 0b */0x344, - /* 0c */0x0d4, - /* 0d */0x2c4, - /* 0e */0x1c4, - /* 0f */0x68b, - /* 10 */0x64b, - /* 11 */0x234, - /* 12 */0x134, - /* 13 */0x324, - /* 14 */0x0b4, - /* 15 */0x2a4, - /* 16 */0x1a4, - /* 17 */0x45b, - /* 18 */0x4cb, - /* 19 */0x264, - /* 1a */0x164, - /* 1b */0x49b, - /* 1c */0x0e4, - /* 1d */0x51b, - /* 1e */0x61b, - /* 1f */0x54b, - /* 20 */0x189, - /* 21 */0x229, - /* 22 */0x129, - /* 23 */0x719, - /* 24 */0x0a9, - /* 25 */0x699, - /* 26 */0x599, - /* 27 */0x479, - /* 28 */0x069, - /* 29 */0x659, - /* 2a */0x559, - /* 2b */0x749, - /* 2c */0x4d9, - /* 2d */0x6c9, - /* 2e */0x5c9, - /* 2f */0x289, - /* 30 */0x249, - /* 31 */0x639, - /* 32 */0x539, - /* 33 */0x729, - /* 34 */0x4b9, - /* 35 */0x6a9, - /* 36 */0x5a9, - /* 37 */0x059, - /* 38 */0x0c9, - /* 39 */0x669, - /* 3a */0x569, - /* 3b */0x099, - /* 3c */0x4e9, - /* 3d */0x119, - /* 3e */0x219, - /* 3f */0x149, - /* 40 */0x185, - /* 41 */0x225, - /* 42 */0x125, - /* 43 */0x715, - /* 44 */0x0a5, - /* 45 */0x695, - /* 46 */0x595, - /* 47 */0x475, - /* 48 */0x065, - /* 49 */0x655, - /* 4a */0x555, - /* 4b */0x745, - /* 4c */0x4d5, - /* 4d */0x6c5, - /* 4e */0x5c5, - /* 4f */0x285, - /* 50 */0x245, - /* 51 */0x635, - /* 52 */0x535, - /* 53 */0x725, - /* 54 */0x4b5, - /* 55 */0x6a5, - /* 56 */0x5a5, - /* 57 */0x055, - /* 58 */0x0c5, - /* 59 */0x665, - /* 5a */0x565, - /* 5b */0x095, - /* 5c */0x4e5, - /* 5d */0x115, - /* 5e */0x215, - /* 5f */0x145, - /* 60 */0x18c, - /* 61 */0x22c, - /* 62 */0x12c, - /* 63 */0x713, - /* 64 */0x0ac, - /* 65 */0x693, - /* 66 */0x593, - /* 67 */0x473, - /* 68 */0x06c, - /* 69 */0x653, - /* 6a */0x553, - /* 6b */0x743, - /* 6c */0x4d3, - /* 6d */0x6c3, - /* 6e */0x5c3, - /* 6f */0x28c, - /* 70 */0x24c, - /* 71 */0x633, - /* 72 */0x533, - /* 73 */0x723, - /* 74 */0x4b3, - /* 75 */0x6a3, - /* 76 */0x5a3, - /* 77 */0x05c, - /* 78 */0x0cc, - /* 79 */0x663, - /* 7a */0x563, - /* 7b */0x09c, - /* 7c */0x4e3, - /* 7d */0x11c, - /* 7e */0x21c, - /* 7f */0x14c, - /* 80 */0x58d, - /* 81 */0x62d, - /* 82 */0x52d, - /* 83 */0x312, - /* 84 */0x4ad, - /* 85 */0x292, - /* 86 */0x192, - /* 87 */0x072, - /* 88 */0x46d, - /* 89 */0x252, - /* 8a */0x152, - /* 8b */0x342, - /* 8c */0x0d2, - /* 8d */0x2c2, - /* 8e */0x1c2, - /* 8f */0x68d, - /* 90 */0x64d, - /* 91 */0x232, - /* 92 */0x132, - /* 93 */0x322, - /* 94 */0x0b2, - /* 95 */0x2a2, - /* 96 */0x1a2, - /* 97 */0x45d, - /* 98 */0x4cd, - /* 99 */0x262, - /* 9a */0x162, - /* 9b */0x49d, - /* 9c */0x0e2, - /* 9d */0x51d, - /* 9e */0x61d, - /* 9f */0x54d, - /* a0 */0x18a, - /* a1 */0x22a, - /* a2 */0x12a, - /* a3 */0x71a, - /* a4 */0x0aa, - /* a5 */0x69a, - /* a6 */0x59a, - /* a7 */0x47a, - /* a8 */0x06a, - /* a9 */0x65a, - /* aa */0x55a, - /* ab */0x74a, - /* ac */0x4da, - /* ad */0x6ca, - /* ae */0x5ca, - /* af */0x28a, - /* b0 */0x24a, - /* b1 */0x63a, - /* b2 */0x53a, - /* b3 */0x72a, - /* b4 */0x4ba, - /* b5 */0x6aa, - /* b6 */0x5aa, - /* b7 */0x05a, - /* b8 */0x0ca, - /* b9 */0x66a, - /* ba */0x56a, - /* bb */0x09a, - /* bc */0x4ea, - /* bd */0x11a, - /* be */0x21a, - /* bf */0x14a, - /* c0 */0x186, - /* c1 */0x226, - /* c2 */0x126, - /* c3 */0x716, - /* c4 */0x0a6, - /* c5 */0x696, - /* c6 */0x596, - /* c7 */0x476, - /* c8 */0x066, - /* c9 */0x656, - /* ca */0x556, - /* cb */0x746, - /* cc */0x4d6, - /* cd */0x6c6, - /* ce */0x5c6, - /* cf */0x286, - /* d0 */0x246, - /* d1 */0x636, - /* d2 */0x536, - /* d3 */0x726, - /* d4 */0x4b6, - /* d5 */0x6a6, - /* d6 */0x5a6, - /* d7 */0x056, - /* d8 */0x0c6, - /* d9 */0x666, - /* da */0x566, - /* db */0x096, - /* dc */0x4e6, - /* dd */0x116, - /* de */0x216, - /* df */0x146, - /* e0 */0x58e, - /* e1 */0x62e, - /* e2 */0x52e, - /* e3 */0x311, - /* e4 */0x4ae, - /* e5 */0x291, - /* e6 */0x191, - /* e7 */0x071, - /* e8 */0x46e, - /* e9 */0x251, - /* ea */0x151, - /* eb */0x348, - /* ec */0x0d1, - /* ed */0x2c8, - /* ee */0x1c8, - /* ef */0x68e, - /* f0 */0x64e, - /* f1 */0x231, - /* f2 */0x131, - /* f3 */0x321, - /* f4 */0x0b1, - /* f5 */0x2a1, - /* f6 */0x1a1, - /* f7 */0x45e, - /* f8 */0x4ce, - /* f9 */0x261, - /* fa */0x161, - /* fb */0x49e, - /* fc */0x0e1, - /* fd */0x51e, - /* fe */0x61e, - /* ff */0x54e, } }; + { + /* 00 */0x274, + /* 01 */0x1d4, + /* 02 */0x2d4, + /* 03 */0x71b, + /* 04 */0x354, + /* 05 */0x69b, + /* 06 */0x59b, + /* 07 */0x78b, + /* 08 */0x394, + /* 09 */0x65b, + /* 0a */0x55b, + /* 0b */0x74b, + /* 0c */0x4db, + /* 0d */0x6cb, + /* 0e */0x5cb, + /* 0f */0x174, + /* 10 */0x1b4, + /* 11 */0x63b, + /* 12 */0x53b, + /* 13 */0x72b, + /* 14 */0x4bb, + /* 15 */0x6ab, + /* 16 */0x5ab, + /* 17 */0x3a4, + /* 18 */0x334, + /* 19 */0x66b, + /* 1a */0x56b, + /* 1b */0x364, + /* 1c */0x4eb, + /* 1d */0x2e4, + /* 1e */0x1e4, + /* 1f */0x2b4, + /* 20 */0x679, + /* 21 */0x5d9, + /* 22 */0x6d9, + /* 23 */0x319, + /* 24 */0x759, + /* 25 */0x299, + /* 26 */0x199, + /* 27 */0x389, + /* 28 */0x799, + /* 29 */0x259, + /* 2a */0x159, + /* 2b */0x349, + /* 2c */0x0d9, + /* 2d */0x2c9, + /* 2e */0x1c9, + /* 2f */0x579, + /* 30 */0x5b9, + /* 31 */0x239, + /* 32 */0x139, + /* 33 */0x329, + /* 34 */0x0b9, + /* 35 */0x2a9, + /* 36 */0x1a9, + /* 37 */0x7a9, + /* 38 */0x739, + /* 39 */0x269, + /* 3a */0x169, + /* 3b */0x769, + /* 3c */0x0e9, + /* 3d */0x6e9, + /* 3e */0x5e9, + /* 3f */0x6b9, + /* 40 */0x675, + /* 41 */0x5d5, + /* 42 */0x6d5, + /* 43 */0x315, + /* 44 */0x755, + /* 45 */0x295, + /* 46 */0x195, + /* 47 */0x385, + /* 48 */0x795, + /* 49 */0x255, + /* 4a */0x155, + /* 4b */0x345, + /* 4c */0x0d5, + /* 4d */0x2c5, + /* 4e */0x1c5, + /* 4f */0x575, + /* 50 */0x5b5, + /* 51 */0x235, + /* 52 */0x135, + /* 53 */0x325, + /* 54 */0x0b5, + /* 55 */0x2a5, + /* 56 */0x1a5, + /* 57 */0x7a5, + /* 58 */0x735, + /* 59 */0x265, + /* 5a */0x165, + /* 5b */0x765, + /* 5c */0x0e5, + /* 5d */0x6e5, + /* 5e */0x5e5, + /* 5f */0x6b5, + /* 60 */0x673, + /* 61 */0x5d3, + /* 62 */0x6d3, + /* 63 */0x31c, + /* 64 */0x753, + /* 65 */0x29c, + /* 66 */0x19c, + /* 67 */0x38c, + /* 68 */0x793, + /* 69 */0x25c, + /* 6a */0x15c, + /* 6b */0x34c, + /* 6c */0x0dc, + /* 6d */0x2cc, + /* 6e */0x1cc, + /* 6f */0x573, + /* 70 */0x5b3, + /* 71 */0x23c, + /* 72 */0x13c, + /* 73 */0x32c, + /* 74 */0x0bc, + /* 75 */0x2ac, + /* 76 */0x1ac, + /* 77 */0x7a3, + /* 78 */0x733, + /* 79 */0x26c, + /* 7a */0x16c, + /* 7b */0x763, + /* 7c */0x0ec, + /* 7d */0x6e3, + /* 7e */0x5e3, + /* 7f */0x6b3, + /* 80 */0x272, + /* 81 */0x1d2, + /* 82 */0x2d2, + /* 83 */0x71d, + /* 84 */0x352, + /* 85 */0x69d, + /* 86 */0x59d, + /* 87 */0x78d, + /* 88 */0x392, + /* 89 */0x65d, + /* 8a */0x55d, + /* 8b */0x74d, + /* 8c */0x4dd, + /* 8d */0x6cd, + /* 8e */0x5cd, + /* 8f */0x172, + /* 90 */0x1b2, + /* 91 */0x63d, + /* 92 */0x53d, + /* 93 */0x72d, + /* 94 */0x4bd, + /* 95 */0x6ad, + /* 96 */0x5ad, + /* 97 */0x3a2, + /* 98 */0x332, + /* 99 */0x66d, + /* 9a */0x56d, + /* 9b */0x362, + /* 9c */0x4ed, + /* 9d */0x2e2, + /* 9e */0x1e2, + /* 9f */0x2b2, + /* a0 */0x67a, + /* a1 */0x5da, + /* a2 */0x6da, + /* a3 */0x31a, + /* a4 */0x75a, + /* a5 */0x29a, + /* a6 */0x19a, + /* a7 */0x38a, + /* a8 */0x79a, + /* a9 */0x25a, + /* aa */0x15a, + /* ab */0x34a, + /* ac */0x0da, + /* ad */0x2ca, + /* ae */0x1ca, + /* af */0x57a, + /* b0 */0x5ba, + /* b1 */0x23a, + /* b2 */0x13a, + /* b3 */0x32a, + /* b4 */0x0ba, + /* b5 */0x2aa, + /* b6 */0x1aa, + /* b7 */0x7aa, + /* b8 */0x73a, + /* b9 */0x26a, + /* ba */0x16a, + /* bb */0x76a, + /* bc */0x0ea, + /* bd */0x6ea, + /* be */0x5ea, + /* bf */0x6ba, + /* c0 */0x676, + /* c1 */0x5d6, + /* c2 */0x6d6, + /* c3 */0x316, + /* c4 */0x756, + /* c5 */0x296, + /* c6 */0x196, + /* c7 */0x386, + /* c8 */0x796, + /* c9 */0x256, + /* ca */0x156, + /* cb */0x346, + /* cc */0x0d6, + /* cd */0x2c6, + /* ce */0x1c6, + /* cf */0x576, + /* d0 */0x5b6, + /* d1 */0x236, + /* d2 */0x136, + /* d3 */0x326, + /* d4 */0x0b6, + /* d5 */0x2a6, + /* d6 */0x1a6, + /* d7 */0x7a6, + /* d8 */0x736, + /* d9 */0x266, + /* da */0x166, + /* db */0x766, + /* dc */0x0e6, + /* dd */0x6e6, + /* de */0x5e6, + /* df */0x6b6, + /* e0 */0x271, + /* e1 */0x1d1, + /* e2 */0x2d1, + /* e3 */0x71e, + /* e4 */0x351, + /* e5 */0x69e, + /* e6 */0x59e, + /* e7 */0x78e, + /* e8 */0x391, + /* e9 */0x65e, + /* ea */0x55e, + /* eb */0x74e, + /* ec */0x4de, + /* ed */0x6ce, + /* ee */0x5ce, + /* ef */0x171, + /* f0 */0x1b1, + /* f1 */0x637, + /* f2 */0x537, + /* f3 */0x72e, + /* f4 */0x4b7, + /* f5 */0x6ae, + /* f6 */0x5ae, + /* f7 */0x3a1, + /* f8 */0x331, + /* f9 */0x66e, + /* fa */0x56e, + /* fb */0x361, + /* fc */0x4ee, + /* fd */0x2e1, + /* fe */0x1e1, + /* ff */0x2b1, + }, // RD = +1 cases + { + /* 00 */0x58b, + /* 01 */0x62b, + /* 02 */0x52b, + /* 03 */0x314, + /* 04 */0x4ab, + /* 05 */0x294, + /* 06 */0x194, + /* 07 */0x074, + /* 08 */0x46b, + /* 09 */0x254, + /* 0a */0x154, + /* 0b */0x344, + /* 0c */0x0d4, + /* 0d */0x2c4, + /* 0e */0x1c4, + /* 0f */0x68b, + /* 10 */0x64b, + /* 11 */0x234, + /* 12 */0x134, + /* 13 */0x324, + /* 14 */0x0b4, + /* 15 */0x2a4, + /* 16 */0x1a4, + /* 17 */0x45b, + /* 18 */0x4cb, + /* 19 */0x264, + /* 1a */0x164, + /* 1b */0x49b, + /* 1c */0x0e4, + /* 1d */0x51b, + /* 1e */0x61b, + /* 1f */0x54b, + /* 20 */0x189, + /* 21 */0x229, + /* 22 */0x129, + /* 23 */0x719, + /* 24 */0x0a9, + /* 25 */0x699, + /* 26 */0x599, + /* 27 */0x479, + /* 28 */0x069, + /* 29 */0x659, + /* 2a */0x559, + /* 2b */0x749, + /* 2c */0x4d9, + /* 2d */0x6c9, + /* 2e */0x5c9, + /* 2f */0x289, + /* 30 */0x249, + /* 31 */0x639, + /* 32 */0x539, + /* 33 */0x729, + /* 34 */0x4b9, + /* 35 */0x6a9, + /* 36 */0x5a9, + /* 37 */0x059, + /* 38 */0x0c9, + /* 39 */0x669, + /* 3a */0x569, + /* 3b */0x099, + /* 3c */0x4e9, + /* 3d */0x119, + /* 3e */0x219, + /* 3f */0x149, + /* 40 */0x185, + /* 41 */0x225, + /* 42 */0x125, + /* 43 */0x715, + /* 44 */0x0a5, + /* 45 */0x695, + /* 46 */0x595, + /* 47 */0x475, + /* 48 */0x065, + /* 49 */0x655, + /* 4a */0x555, + /* 4b */0x745, + /* 4c */0x4d5, + /* 4d */0x6c5, + /* 4e */0x5c5, + /* 4f */0x285, + /* 50 */0x245, + /* 51 */0x635, + /* 52 */0x535, + /* 53 */0x725, + /* 54 */0x4b5, + /* 55 */0x6a5, + /* 56 */0x5a5, + /* 57 */0x055, + /* 58 */0x0c5, + /* 59 */0x665, + /* 5a */0x565, + /* 5b */0x095, + /* 5c */0x4e5, + /* 5d */0x115, + /* 5e */0x215, + /* 5f */0x145, + /* 60 */0x18c, + /* 61 */0x22c, + /* 62 */0x12c, + /* 63 */0x713, + /* 64 */0x0ac, + /* 65 */0x693, + /* 66 */0x593, + /* 67 */0x473, + /* 68 */0x06c, + /* 69 */0x653, + /* 6a */0x553, + /* 6b */0x743, + /* 6c */0x4d3, + /* 6d */0x6c3, + /* 6e */0x5c3, + /* 6f */0x28c, + /* 70 */0x24c, + /* 71 */0x633, + /* 72 */0x533, + /* 73 */0x723, + /* 74 */0x4b3, + /* 75 */0x6a3, + /* 76 */0x5a3, + /* 77 */0x05c, + /* 78 */0x0cc, + /* 79 */0x663, + /* 7a */0x563, + /* 7b */0x09c, + /* 7c */0x4e3, + /* 7d */0x11c, + /* 7e */0x21c, + /* 7f */0x14c, + /* 80 */0x58d, + /* 81 */0x62d, + /* 82 */0x52d, + /* 83 */0x312, + /* 84 */0x4ad, + /* 85 */0x292, + /* 86 */0x192, + /* 87 */0x072, + /* 88 */0x46d, + /* 89 */0x252, + /* 8a */0x152, + /* 8b */0x342, + /* 8c */0x0d2, + /* 8d */0x2c2, + /* 8e */0x1c2, + /* 8f */0x68d, + /* 90 */0x64d, + /* 91 */0x232, + /* 92 */0x132, + /* 93 */0x322, + /* 94 */0x0b2, + /* 95 */0x2a2, + /* 96 */0x1a2, + /* 97 */0x45d, + /* 98 */0x4cd, + /* 99 */0x262, + /* 9a */0x162, + /* 9b */0x49d, + /* 9c */0x0e2, + /* 9d */0x51d, + /* 9e */0x61d, + /* 9f */0x54d, + /* a0 */0x18a, + /* a1 */0x22a, + /* a2 */0x12a, + /* a3 */0x71a, + /* a4 */0x0aa, + /* a5 */0x69a, + /* a6 */0x59a, + /* a7 */0x47a, + /* a8 */0x06a, + /* a9 */0x65a, + /* aa */0x55a, + /* ab */0x74a, + /* ac */0x4da, + /* ad */0x6ca, + /* ae */0x5ca, + /* af */0x28a, + /* b0 */0x24a, + /* b1 */0x63a, + /* b2 */0x53a, + /* b3 */0x72a, + /* b4 */0x4ba, + /* b5 */0x6aa, + /* b6 */0x5aa, + /* b7 */0x05a, + /* b8 */0x0ca, + /* b9 */0x66a, + /* ba */0x56a, + /* bb */0x09a, + /* bc */0x4ea, + /* bd */0x11a, + /* be */0x21a, + /* bf */0x14a, + /* c0 */0x186, + /* c1 */0x226, + /* c2 */0x126, + /* c3 */0x716, + /* c4 */0x0a6, + /* c5 */0x696, + /* c6 */0x596, + /* c7 */0x476, + /* c8 */0x066, + /* c9 */0x656, + /* ca */0x556, + /* cb */0x746, + /* cc */0x4d6, + /* cd */0x6c6, + /* ce */0x5c6, + /* cf */0x286, + /* d0 */0x246, + /* d1 */0x636, + /* d2 */0x536, + /* d3 */0x726, + /* d4 */0x4b6, + /* d5 */0x6a6, + /* d6 */0x5a6, + /* d7 */0x056, + /* d8 */0x0c6, + /* d9 */0x666, + /* da */0x566, + /* db */0x096, + /* dc */0x4e6, + /* dd */0x116, + /* de */0x216, + /* df */0x146, + /* e0 */0x58e, + /* e1 */0x62e, + /* e2 */0x52e, + /* e3 */0x311, + /* e4 */0x4ae, + /* e5 */0x291, + /* e6 */0x191, + /* e7 */0x071, + /* e8 */0x46e, + /* e9 */0x251, + /* ea */0x151, + /* eb */0x348, + /* ec */0x0d1, + /* ed */0x2c8, + /* ee */0x1c8, + /* ef */0x68e, + /* f0 */0x64e, + /* f1 */0x231, + /* f2 */0x131, + /* f3 */0x321, + /* f4 */0x0b1, + /* f5 */0x2a1, + /* f6 */0x1a1, + /* f7 */0x45e, + /* f8 */0x4ce, + /* f9 */0x261, + /* fa */0x161, + /* fb */0x49e, + /* fc */0x0e1, + /* fd */0x51e, + /* fe */0x61e, + /* ff */0x54e, + } + }; }; } // namespace satnogs diff --git a/include/satnogs/ax25.h b/include/satnogs/ax25.h index fbcd456..d367bed 100644 --- a/include/satnogs/ax25.h +++ b/include/satnogs/ax25.h @@ -27,424 +27,418 @@ #include #include -namespace gr +namespace gr { + +namespace satnogs { +const size_t AX25_MIN_ADDR_LEN = 14; +const size_t AX25_MAX_ADDR_LEN = 28; +const size_t AX25_MIN_CTRL_LEN = 1; +const size_t AX25_MAX_CTRL_LEN = 2; +const size_t AX25_MAX_FRAME_LEN = 256; +const uint8_t AX25_SYNC_FLAG = 0x7E; +const uint8_t AX25_CALLSIGN_MAX_LEN = 6; +const float AX25_SYNC_FLAG_MAP[8] = +{ -1, 1, 1, 1, 1, 1, 1, -1 }; +const uint8_t AX25_SYNC_FLAG_MAP_BIN[8] = +{ 0, 1, 1, 1, 1, 1, 1, 0 }; +/** + * AX.25 Frame types + */ +typedef enum { + AX25_I_FRAME, //!< AX25_I_FRAME Information frame + AX25_S_FRAME, //!< AX25_S_FRAME Supervisory frame + AX25_U_FRAME, //!< AX25_U_FRAME Unnumbered frame + AX25_UI_FRAME /**!< AX25_UI_FRAME Unnumbered information frame */ +} ax25_frame_type_t; + +typedef enum { + AX25_ENC_FAIL, AX25_ENC_OK +} ax25_encode_status_t; + +typedef enum { + AX25_DEC_FAIL, AX25_DEC_OK +} ax25_decode_status_t; + +typedef struct { + uint8_t address[AX25_MAX_ADDR_LEN]; + size_t address_len; + uint16_t ctrl; + size_t ctrl_len; + uint8_t pid; + uint8_t *info; + size_t info_len; + ax25_frame_type_t type; +} ax25_frame_t; + +/** + * Calculates the FCS of the AX25 frame + * @param buffer data buffer + * @param len size of the buffer + * @return the FCS of the buffer + */ +static inline uint16_t +ax25_fcs(uint8_t *buffer, size_t len) { + return crc::crc16_ax25(buffer, len); +} - namespace satnogs - { - const size_t AX25_MIN_ADDR_LEN = 14; - const size_t AX25_MAX_ADDR_LEN = 28; - const size_t AX25_MIN_CTRL_LEN = 1; - const size_t AX25_MAX_CTRL_LEN = 2; - const size_t AX25_MAX_FRAME_LEN = 256; - const uint8_t AX25_SYNC_FLAG = 0x7E; - const uint8_t AX25_CALLSIGN_MAX_LEN = 6; - const float AX25_SYNC_FLAG_MAP[8] = - { -1, 1, 1, 1, 1, 1, 1, -1 }; - const uint8_t AX25_SYNC_FLAG_MAP_BIN[8] = - { 0, 1, 1, 1, 1, 1, 1, 0 }; - /** - * AX.25 Frame types +/** + * Creates the header field of the AX.25 frame + * @param out the output buffer with enough memory to hold the address field + * @param dest_addr the destination callsign address + * @param dest_ssid the destination SSID + * @param src_addr the callsign of the source + * @param src_ssid the source SSID + */ +static inline size_t +ax25_create_addr_field(uint8_t *out, std::string dest_addr, + uint8_t dest_ssid, std::string src_addr, + uint8_t src_ssid) +{ + size_t i; + + for (i = 0; i < dest_addr.length(); i++) { + *out++ = dest_addr[i] << 1; + } + /* + * Perhaps the destination callsign was smaller that the maximum allowed. + * In this case the leftover bytes should be filled with space + */ + for (; i < AX25_CALLSIGN_MAX_LEN; i++) { + *out++ = ' ' << 1; + } + /* Apply SSID, reserved and C bit */ + /* FIXME: C bit is set to 0 implicitly */ + *out++ = ((0b1111 & dest_ssid) << 1) | 0b01100000; + + for (i = 0; i < src_addr.length(); i++) { + *out++ = src_addr[i] << 1; + } + for (; i < AX25_CALLSIGN_MAX_LEN; i++) { + *out++ = ' ' << 1; + } + /* Apply SSID, reserved and C bit. As this is the last address field + * the trailing bit is set to 1. + * / + /* FIXME: C bit is set to 0 implicitly */ + *out++ = ((0b1111 & src_ssid) << 1) | 0b01100001; + return AX25_MIN_ADDR_LEN; +} + +/** + * Gets the destination SSID of an AX.25 frame + * @param in the AX.25 frame buffer + * @return the destination SSID + */ +static inline uint8_t +ax25_get_dest_ssid(const uint8_t *in) +{ + uint8_t ret; + ret = in[AX25_CALLSIGN_MAX_LEN]; + return (ret >> 1) & 0b1111; +} + +static inline size_t +ax25_prepare_frame(uint8_t *out, const uint8_t *info, size_t info_len, + ax25_frame_type_t type, uint8_t *addr, size_t addr_len, + uint16_t ctrl, size_t ctrl_len, size_t preamble_len, + size_t postamble_len) +{ + uint16_t fcs; + size_t i; + if (info_len > AX25_MAX_FRAME_LEN) { + return 0; + } + + memset(out, AX25_SYNC_FLAG, preamble_len); + i = preamble_len; + + /* Insert address and control fields */ + if (addr_len == AX25_MIN_ADDR_LEN || addr_len == AX25_MAX_ADDR_LEN) { + memcpy(out + i, addr, addr_len); + i += addr_len; + } + else { + return 0; + } + + if (ctrl_len == AX25_MIN_CTRL_LEN || ctrl_len == AX25_MAX_CTRL_LEN) { + memcpy(out + i, &ctrl, ctrl_len); + i += ctrl_len; + } + else { + return 0; + } + + /* + * Set the PID depending the frame type. + * FIXME: For now, only the "No layer 3 is implemented" information is + * inserted + */ + if (type == AX25_I_FRAME || type == AX25_UI_FRAME) { + out[i++] = 0xF0; + } + memcpy(out + i, info, info_len); + i += info_len; + + /* Compute the FCS. Ignore the first flag byte */ + fcs = ax25_fcs(out + preamble_len, i - preamble_len); + /* The MS bits are sent first ONLY at the FCS field */ + out[i++] = fcs & 0xFF; + out[i++] = (fcs >> 8) & 0xFF; + memset(out + i, AX25_SYNC_FLAG, postamble_len); + for (size_t j = preamble_len; j < i; j++) { + printf("0x%02x ", out[j]); + } + printf("\n"); + return i + postamble_len; +} + +/** + * Constructs an AX.25 by performing NRZ encoding and bit stuffing + * @param out the output buffer to hold the frame. Note that due to + * the NRZ encoding the output would be [-1, 1]. Also the size of the + * buffer should be enough, such that the extra stuffed bits are fitting + * on the allocated space. + * + * @param out_len due to bit stuffing the output size can vary. This + * pointer will hold the resulting frame size after bit stuffing. + * + * @param buffer buffer holding the data that should be encoded. + * Note that this buffer SHOULD contain the leading and trailing + * synchronization flag, all necessary headers and the CRC. + * + * @param buffer_len the length of the input buffer. + * + * @param preamble_len the number of consecutive AX.25 flags that will + * be placed in the preamble. This preamble will be NOT bit-stuffed. + * + * @param postamble_len the number of consecutive AX.25 flags that will + * be placed in the postamble. This postamble will be NOT bit-stuffed. + * + * @return the resulting status of the encoding + */ +static inline ax25_encode_status_t +ax25_nrz_bit_stuffing(float *out, size_t *out_len, const uint8_t *buffer, + size_t buffer_len, size_t preamble_len, + size_t postamble_len) +{ + uint8_t bit; + uint8_t prev_bit = 0; + size_t out_idx = 0; + size_t bit_idx; + size_t cont_1 = 0; + size_t total_cont_1 = 0; + size_t i; + + /* Leading FLAG field does not need bit stuffing */ + for (i = 0; i < preamble_len; i++) { + memcpy(out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float)); + out_idx += 8; + } + + /* Skip the leading and trailing FLAG field */ + buffer += preamble_len; + for (i = 0; i < 8 * (buffer_len - preamble_len - postamble_len); i++) { + bit = (buffer[i / 8] >> (i % 8)) & 0x1; + out[out_idx++] = bit ? 1.0 : -1.0; + + /* Check if bit stuffing should be applied */ + if (bit & prev_bit) { + cont_1++; + total_cont_1++; + if (cont_1 == 4) { + out[out_idx++] = -1.0; + cont_1 = 0; + } + } + else { + cont_1 = total_cont_1 = 0; + } + prev_bit = bit; + + /* + * If the total number of continuous 1's is 15 the the frame should be + * dropped */ - typedef enum - { - AX25_I_FRAME, //!< AX25_I_FRAME Information frame - AX25_S_FRAME, //!< AX25_S_FRAME Supervisory frame - AX25_U_FRAME, //!< AX25_U_FRAME Unnumbered frame - AX25_UI_FRAME /**!< AX25_UI_FRAME Unnumbered information frame */ - } ax25_frame_type_t; + if (total_cont_1 >= 14) { + return AX25_ENC_FAIL; + } + } - typedef enum - { - AX25_ENC_FAIL, AX25_ENC_OK - } ax25_encode_status_t; + /* Trailing FLAG field does not need bit stuffing */ + for (i = 0; i < postamble_len; i++) { + memcpy(out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float)); + out_idx += 8; + } - typedef enum - { - AX25_DEC_FAIL, AX25_DEC_OK - } ax25_decode_status_t; + *out_len = out_idx; + return AX25_ENC_OK; +} - typedef struct - { - uint8_t address[AX25_MAX_ADDR_LEN]; - size_t address_len; - uint16_t ctrl; - size_t ctrl_len; - uint8_t pid; - uint8_t *info; - size_t info_len; - ax25_frame_type_t type; - } ax25_frame_t; +/** + * Constructs an AX.25 by performing bit stuffing. + * @param out the output buffer to hold the frame. To keep it simple, + * each byte of the buffer holds only one bit. Also the size of the + * buffer should be enough, such that the extra stuffed bits are fitting + * on the allocated space. + * + * @param out_len due to bit stuffing the output size can vary. This + * pointer will hold the resulting frame size after bit stuffing. + * + * @param buffer buffer holding the data that should be encoded. + * Note that this buffer SHOULD contain the leading and trailing + * synchronization flag, all necessary headers and the CRC. + * + * @param buffer_len the length of the input buffer. + * + * @param preamble_len the number of consecutive AX.25 flags that will + * be placed in the preamble. This preamble will be NOT bit-stuffed. + * + * @param postamble_len the number of consecutive AX.25 flags that will + * be placed in the postamble. This postamble will be NOT bit-stuffed. + * + * @return the resulting status of the encoding + */ +static inline ax25_encode_status_t +ax25_bit_stuffing(uint8_t *out, size_t *out_len, const uint8_t *buffer, + const size_t buffer_len, size_t preamble_len, + size_t postamble_len) +{ + uint8_t bit; + uint8_t shift_reg = 0x0; + size_t out_idx = 0; + size_t bit_idx; + size_t i; - /** - * Calculates the FCS of the AX25 frame - * @param buffer data buffer - * @param len size of the buffer - * @return the FCS of the buffer - */ - static inline uint16_t - ax25_fcs (uint8_t *buffer, size_t len) - { - return crc::crc16_ax25(buffer, len); + /* Leading FLAG field does not need bit stuffing */ + for (i = 0; i < preamble_len; i++) { + memcpy(out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t)); + out_idx += 8; + } + + /* Skip the leading and trailing FLAG field */ + buffer += preamble_len; + for (i = 0; i < 8 * (buffer_len - preamble_len - postamble_len); i++) { + bit = (buffer[i / 8] >> (i % 8)) & 0x1; + shift_reg = (shift_reg << 1) | bit; + out[out_idx++] = bit; + + /* Check if bit stuffing should be applied */ + if ((shift_reg & 0x1F) == 0x1F) { + out[out_idx++] = 0x0; + shift_reg <<= 1; + } + } + + /* Trailing FLAG field does not need bit stuffing */ + for (i = 0; i < postamble_len; i++) { + memcpy(out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t)); + out_idx += 8; + } + + *out_len = out_idx; + return AX25_ENC_OK; +} + +static inline ax25_decode_status_t +ax25_decode(uint8_t *out, size_t *out_len, const uint8_t *ax25_frame, + size_t len) +{ + size_t i; + size_t frame_start = UINT_MAX; + size_t frame_stop = UINT_MAX; + uint8_t res; + size_t cont_1 = 0; + size_t received_bytes = 0; + size_t bit_cnt = 0; + uint8_t decoded_byte = 0x0; + uint16_t fcs; + uint16_t recv_fcs; + + /* Start searching for the SYNC flag */ + for (i = 0; i < len - sizeof(AX25_SYNC_FLAG_MAP_BIN); i++) { + res = (AX25_SYNC_FLAG_MAP_BIN[0] ^ ax25_frame[i]) + | (AX25_SYNC_FLAG_MAP_BIN[1] ^ ax25_frame[i + 1]) + | (AX25_SYNC_FLAG_MAP_BIN[2] ^ ax25_frame[i + 2]) + | (AX25_SYNC_FLAG_MAP_BIN[3] ^ ax25_frame[i + 3]) + | (AX25_SYNC_FLAG_MAP_BIN[4] ^ ax25_frame[i + 4]) + | (AX25_SYNC_FLAG_MAP_BIN[5] ^ ax25_frame[i + 5]) + | (AX25_SYNC_FLAG_MAP_BIN[6] ^ ax25_frame[i + 6]) + | (AX25_SYNC_FLAG_MAP_BIN[7] ^ ax25_frame[i + 7]); + /* Found it! */ + if (res == 0) { + frame_start = i; + break; + } + } + + /* We failed to find the SYNC flag */ + if (frame_start == UINT_MAX) { + return AX25_DEC_FAIL; + } + + for (i = frame_start + sizeof(AX25_SYNC_FLAG_MAP_BIN); + i < len - sizeof(AX25_SYNC_FLAG_MAP_BIN) + 1; i++) { + /* Check if we reached the frame end */ + res = (AX25_SYNC_FLAG_MAP_BIN[0] ^ ax25_frame[i]) + | (AX25_SYNC_FLAG_MAP_BIN[1] ^ ax25_frame[i + 1]) + | (AX25_SYNC_FLAG_MAP_BIN[2] ^ ax25_frame[i + 2]) + | (AX25_SYNC_FLAG_MAP_BIN[3] ^ ax25_frame[i + 3]) + | (AX25_SYNC_FLAG_MAP_BIN[4] ^ ax25_frame[i + 4]) + | (AX25_SYNC_FLAG_MAP_BIN[5] ^ ax25_frame[i + 5]) + | (AX25_SYNC_FLAG_MAP_BIN[6] ^ ax25_frame[i + 6]) + | (AX25_SYNC_FLAG_MAP_BIN[7] ^ ax25_frame[i + 7]); + /* Found it! */ + if (res == 0) { + frame_stop = i; + break; } - /** - * Creates the header field of the AX.25 frame - * @param out the output buffer with enough memory to hold the address field - * @param dest_addr the destination callsign address - * @param dest_ssid the destination SSID - * @param src_addr the callsign of the source - * @param src_ssid the source SSID - */ - static inline size_t - ax25_create_addr_field (uint8_t *out, std::string dest_addr, - uint8_t dest_ssid, std::string src_addr, - uint8_t src_ssid) - { - size_t i; - - for (i = 0; i < dest_addr.length (); i++) { - *out++ = dest_addr[i] << 1; - } - /* - * Perhaps the destination callsign was smaller that the maximum allowed. - * In this case the leftover bytes should be filled with space - */ - for (; i < AX25_CALLSIGN_MAX_LEN; i++) { - *out++ = ' ' << 1; - } - /* Apply SSID, reserved and C bit */ - /* FIXME: C bit is set to 0 implicitly */ - *out++ = ((0b1111 & dest_ssid) << 1) | 0b01100000; - - for (i = 0; i < src_addr.length (); i++) { - *out++ = src_addr[i] << 1; - } - for (; i < AX25_CALLSIGN_MAX_LEN; i++) { - *out++ = ' ' << 1; - } - /* Apply SSID, reserved and C bit. As this is the last address field - * the trailing bit is set to 1. - * / - /* FIXME: C bit is set to 0 implicitly */ - *out++ = ((0b1111 & src_ssid) << 1) | 0b01100001; - return AX25_MIN_ADDR_LEN; + if (ax25_frame[i]) { + cont_1++; + decoded_byte |= 1 << bit_cnt; + bit_cnt++; } - - /** - * Gets the destination SSID of an AX.25 frame - * @param in the AX.25 frame buffer - * @return the destination SSID - */ - static inline uint8_t - ax25_get_dest_ssid (const uint8_t *in) - { - uint8_t ret; - ret = in[AX25_CALLSIGN_MAX_LEN]; - return (ret >> 1) & 0b1111; - } - - static inline size_t - ax25_prepare_frame (uint8_t *out, const uint8_t *info, size_t info_len, - ax25_frame_type_t type, uint8_t *addr, size_t addr_len, - uint16_t ctrl, size_t ctrl_len, size_t preamble_len, - size_t postamble_len) - { - uint16_t fcs; - size_t i; - if (info_len > AX25_MAX_FRAME_LEN) { - return 0; - } - - memset (out, AX25_SYNC_FLAG, preamble_len); - i = preamble_len; - - /* Insert address and control fields */ - if (addr_len == AX25_MIN_ADDR_LEN || addr_len == AX25_MAX_ADDR_LEN) { - memcpy (out + i, addr, addr_len); - i += addr_len; + else { + /* If 5 consecutive 1's drop the extra zero*/ + if (cont_1 >= 5) { + cont_1 = 0; } else { - return 0; + bit_cnt++; + cont_1 = 0; } - - if (ctrl_len == AX25_MIN_CTRL_LEN || ctrl_len == AX25_MAX_CTRL_LEN) { - memcpy (out + i, &ctrl, ctrl_len); - i += ctrl_len; - } - else { - return 0; - } - - /* - * Set the PID depending the frame type. - * FIXME: For now, only the "No layer 3 is implemented" information is - * inserted - */ - if (type == AX25_I_FRAME || type == AX25_UI_FRAME) { - out[i++] = 0xF0; - } - memcpy (out + i, info, info_len); - i += info_len; - - /* Compute the FCS. Ignore the first flag byte */ - fcs = ax25_fcs (out + preamble_len, i - preamble_len); - /* The MS bits are sent first ONLY at the FCS field */ - out[i++] = fcs & 0xFF; - out[i++] = (fcs >> 8) & 0xFF; - memset (out + i, AX25_SYNC_FLAG, postamble_len); - for(size_t j = preamble_len; j < i; j++) { - printf("0x%02x ", out[j]); - } - printf("\n"); - return i + postamble_len; } - /** - * Constructs an AX.25 by performing NRZ encoding and bit stuffing - * @param out the output buffer to hold the frame. Note that due to - * the NRZ encoding the output would be [-1, 1]. Also the size of the - * buffer should be enough, such that the extra stuffed bits are fitting - * on the allocated space. - * - * @param out_len due to bit stuffing the output size can vary. This - * pointer will hold the resulting frame size after bit stuffing. - * - * @param buffer buffer holding the data that should be encoded. - * Note that this buffer SHOULD contain the leading and trailing - * synchronization flag, all necessary headers and the CRC. - * - * @param buffer_len the length of the input buffer. - * - * @param preamble_len the number of consecutive AX.25 flags that will - * be placed in the preamble. This preamble will be NOT bit-stuffed. - * - * @param postamble_len the number of consecutive AX.25 flags that will - * be placed in the postamble. This postamble will be NOT bit-stuffed. - * - * @return the resulting status of the encoding - */ - static inline ax25_encode_status_t - ax25_nrz_bit_stuffing (float *out, size_t *out_len, const uint8_t *buffer, - size_t buffer_len, size_t preamble_len, - size_t postamble_len) - { - uint8_t bit; - uint8_t prev_bit = 0; - size_t out_idx = 0; - size_t bit_idx; - size_t cont_1 = 0; - size_t total_cont_1 = 0; - size_t i; - - /* Leading FLAG field does not need bit stuffing */ - for (i = 0; i < preamble_len; i++) { - memcpy (out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float)); - out_idx += 8; - } - - /* Skip the leading and trailing FLAG field */ - buffer += preamble_len; - for (i = 0; i < 8 * (buffer_len - preamble_len - postamble_len); i++) { - bit = (buffer[i / 8] >> (i % 8)) & 0x1; - out[out_idx++] = bit ? 1.0 : -1.0; - - /* Check if bit stuffing should be applied */ - if (bit & prev_bit) { - cont_1++; - total_cont_1++; - if (cont_1 == 4) { - out[out_idx++] = -1.0; - cont_1 = 0; - } - } - else { - cont_1 = total_cont_1 = 0; - } - prev_bit = bit; - - /* - * If the total number of continuous 1's is 15 the the frame should be - * dropped - */ - if (total_cont_1 >= 14) { - return AX25_ENC_FAIL; - } - } - - /* Trailing FLAG field does not need bit stuffing */ - for (i = 0; i < postamble_len; i++) { - memcpy (out + out_idx, AX25_SYNC_FLAG_MAP, 8 * sizeof(float)); - out_idx += 8; - } - - *out_len = out_idx; - return AX25_ENC_OK; + /* Fill the fully constructed byte */ + if (bit_cnt == 8) { + out[received_bytes++] = decoded_byte; + bit_cnt = 0; + decoded_byte = 0x0; } + } - /** - * Constructs an AX.25 by performing bit stuffing. - * @param out the output buffer to hold the frame. To keep it simple, - * each byte of the buffer holds only one bit. Also the size of the - * buffer should be enough, such that the extra stuffed bits are fitting - * on the allocated space. - * - * @param out_len due to bit stuffing the output size can vary. This - * pointer will hold the resulting frame size after bit stuffing. - * - * @param buffer buffer holding the data that should be encoded. - * Note that this buffer SHOULD contain the leading and trailing - * synchronization flag, all necessary headers and the CRC. - * - * @param buffer_len the length of the input buffer. - * - * @param preamble_len the number of consecutive AX.25 flags that will - * be placed in the preamble. This preamble will be NOT bit-stuffed. - * - * @param postamble_len the number of consecutive AX.25 flags that will - * be placed in the postamble. This postamble will be NOT bit-stuffed. - * - * @return the resulting status of the encoding - */ - static inline ax25_encode_status_t - ax25_bit_stuffing (uint8_t *out, size_t *out_len, const uint8_t *buffer, - const size_t buffer_len, size_t preamble_len, - size_t postamble_len) - { - uint8_t bit; - uint8_t shift_reg = 0x0; - size_t out_idx = 0; - size_t bit_idx; - size_t i; + if (frame_stop == UINT_MAX || received_bytes < AX25_MIN_ADDR_LEN) { + return AX25_DEC_FAIL; + } - /* Leading FLAG field does not need bit stuffing */ - for (i = 0; i < preamble_len; i++) { - memcpy (out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t)); - out_idx += 8; - } + /* Now check the CRC */ + fcs = ax25_fcs(out, received_bytes - sizeof(uint16_t)); + recv_fcs = (((uint16_t) out[received_bytes - 2]) << 8) + | out[received_bytes - 1]; - /* Skip the leading and trailing FLAG field */ - buffer += preamble_len; - for (i = 0; i < 8 * (buffer_len - preamble_len - postamble_len); i++) { - bit = (buffer[i / 8] >> (i % 8)) & 0x1; - shift_reg = (shift_reg << 1) | bit; - out[out_idx++] = bit; + if (fcs != recv_fcs) { + LOG_WARN("AX.25 CRC-16 failed"); + return AX25_DEC_FAIL; + } - /* Check if bit stuffing should be applied */ - if ((shift_reg & 0x1F) == 0x1F) { - out[out_idx++] = 0x0; - shift_reg <<= 1; - } - } + *out_len = received_bytes - sizeof(uint16_t); + return AX25_DEC_OK; - /* Trailing FLAG field does not need bit stuffing */ - for (i = 0; i < postamble_len; i++) { - memcpy (out + out_idx, AX25_SYNC_FLAG_MAP_BIN, 8 * sizeof(uint8_t)); - out_idx += 8; - } +} - *out_len = out_idx; - return AX25_ENC_OK; - } - - static inline ax25_decode_status_t - ax25_decode (uint8_t *out, size_t *out_len, const uint8_t *ax25_frame, - size_t len) - { - size_t i; - size_t frame_start = UINT_MAX; - size_t frame_stop = UINT_MAX; - uint8_t res; - size_t cont_1 = 0; - size_t received_bytes = 0; - size_t bit_cnt = 0; - uint8_t decoded_byte = 0x0; - uint16_t fcs; - uint16_t recv_fcs; - - /* Start searching for the SYNC flag */ - for (i = 0; i < len - sizeof(AX25_SYNC_FLAG_MAP_BIN); i++) { - res = (AX25_SYNC_FLAG_MAP_BIN[0] ^ ax25_frame[i]) - | (AX25_SYNC_FLAG_MAP_BIN[1] ^ ax25_frame[i + 1]) - | (AX25_SYNC_FLAG_MAP_BIN[2] ^ ax25_frame[i + 2]) - | (AX25_SYNC_FLAG_MAP_BIN[3] ^ ax25_frame[i + 3]) - | (AX25_SYNC_FLAG_MAP_BIN[4] ^ ax25_frame[i + 4]) - | (AX25_SYNC_FLAG_MAP_BIN[5] ^ ax25_frame[i + 5]) - | (AX25_SYNC_FLAG_MAP_BIN[6] ^ ax25_frame[i + 6]) - | (AX25_SYNC_FLAG_MAP_BIN[7] ^ ax25_frame[i + 7]); - /* Found it! */ - if (res == 0) { - frame_start = i; - break; - } - } - - /* We failed to find the SYNC flag */ - if (frame_start == UINT_MAX) { - return AX25_DEC_FAIL; - } - - for (i = frame_start + sizeof(AX25_SYNC_FLAG_MAP_BIN); - i < len - sizeof(AX25_SYNC_FLAG_MAP_BIN) + 1; i++) { - /* Check if we reached the frame end */ - res = (AX25_SYNC_FLAG_MAP_BIN[0] ^ ax25_frame[i]) - | (AX25_SYNC_FLAG_MAP_BIN[1] ^ ax25_frame[i + 1]) - | (AX25_SYNC_FLAG_MAP_BIN[2] ^ ax25_frame[i + 2]) - | (AX25_SYNC_FLAG_MAP_BIN[3] ^ ax25_frame[i + 3]) - | (AX25_SYNC_FLAG_MAP_BIN[4] ^ ax25_frame[i + 4]) - | (AX25_SYNC_FLAG_MAP_BIN[5] ^ ax25_frame[i + 5]) - | (AX25_SYNC_FLAG_MAP_BIN[6] ^ ax25_frame[i + 6]) - | (AX25_SYNC_FLAG_MAP_BIN[7] ^ ax25_frame[i + 7]); - /* Found it! */ - if (res == 0) { - frame_stop = i; - break; - } - - if (ax25_frame[i]) { - cont_1++; - decoded_byte |= 1 << bit_cnt; - bit_cnt++; - } - else { - /* If 5 consecutive 1's drop the extra zero*/ - if (cont_1 >= 5) { - cont_1 = 0; - } - else { - bit_cnt++; - cont_1 = 0; - } - } - - /* Fill the fully constructed byte */ - if (bit_cnt == 8) { - out[received_bytes++] = decoded_byte; - bit_cnt = 0; - decoded_byte = 0x0; - } - } - - if (frame_stop == UINT_MAX || received_bytes < AX25_MIN_ADDR_LEN) { - return AX25_DEC_FAIL; - } - - /* Now check the CRC */ - fcs = ax25_fcs (out, received_bytes - sizeof(uint16_t)); - recv_fcs = (((uint16_t) out[received_bytes - 2]) << 8) - | out[received_bytes - 1]; - - if (fcs != recv_fcs) { - LOG_WARN("AX.25 CRC-16 failed"); - return AX25_DEC_FAIL; - } - - *out_len = received_bytes - sizeof(uint16_t); - return AX25_DEC_OK; - - } - - } // namespace satnogs +} // namespace satnogs } // namespace gr diff --git a/include/satnogs/ax25_decoder.h b/include/satnogs/ax25_decoder.h index e04e265..0cb7649 100644 --- a/include/satnogs/ax25_decoder.h +++ b/include/satnogs/ax25_decoder.h @@ -27,10 +27,8 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief AX.25 decoder that supports the legacy hardware radios. @@ -52,8 +50,7 @@ namespace satnogs * \ingroup satnogs * */ -class SATNOGS_API ax25_decoder : public decoder -{ +class SATNOGS_API ax25_decoder : public decoder { public: /** @@ -79,9 +76,9 @@ public: * @return a shared pointer of the decoder instance */ static decoder::decoder_sptr - make (const std::string &addr, uint8_t ssid, bool promisc = false, - bool descramble = true, bool crc_check = true, - size_t max_frame_len = 512); + make(const std::string &addr, uint8_t ssid, bool promisc = false, + bool descramble = true, bool crc_check = true, + size_t max_frame_len = 512); /** * The decoder take as input a quadrature demodulated bit stream. @@ -104,21 +101,20 @@ public: * @param crc_check bypass the CRC check of the frame * @param max_frame_len the maximum allowed frame length */ - ax25_decoder (const std::string &addr, uint8_t ssid, bool promisc = false, - bool descramble = true, bool crc_check = true, - size_t max_frame_len = 512); + ax25_decoder(const std::string &addr, uint8_t ssid, bool promisc = false, + bool descramble = true, bool crc_check = true, + size_t max_frame_len = 512); - ~ax25_decoder (); + ~ax25_decoder(); decoder_status_t - decode (const void *in, int len); + decode(const void *in, int len); void - reset (); + reset(); private: - typedef enum - { + typedef enum { NO_SYNC, IN_SYNC, DECODING } decoding_state_t; @@ -143,21 +139,21 @@ private: size_t d_frame_start; void - reset_state (); + reset_state(); void - enter_sync_state (); + enter_sync_state(); void - enter_decoding_state (); + enter_decoding_state(); bool - enter_frame_end (decoder_status_t& status); + enter_frame_end(decoder_status_t &status); bool - _decode (decoder_status_t& status); + _decode(decoder_status_t &status); inline void - decode_1b (uint8_t in); + decode_1b(uint8_t in); bool - frame_check (); + frame_check(); }; } // namespace satnogs diff --git a/include/satnogs/ax25_encoder_mb.h b/include/satnogs/ax25_encoder_mb.h index c8f5279..326e1a7 100644 --- a/include/satnogs/ax25_encoder_mb.h +++ b/include/satnogs/ax25_encoder_mb.h @@ -24,54 +24,51 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief AX.25 encoder block that supports the legacy hardware radios. - * - * The block takes as inputs blob PMT messages and generates a byte stream. - * Each output byte contains only one LSB, thus the output can be directly - * used for FM modulation. - * - * \ingroup satnogs - * - */ - class SATNOGS_API ax25_encoder_mb : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief AX.25 encoder block that supports the legacy hardware radios. + * + * The block takes as inputs blob PMT messages and generates a byte stream. + * Each output byte contains only one LSB, thus the output can be directly + * used for FM modulation. + * + * \ingroup satnogs + * + */ +class SATNOGS_API ax25_encoder_mb : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /** - * AX.25 encoder block that supports the legacy hardware radios. - * - * The block takes as inputs blob PMT messages and generates a byte stream. - * Each output byte contains only one LSB, thus the output can be directly - * used for FM modulation. - * - * @param dest_addr the destination callsign - * @param dest_ssid the destination SSID - * @param src_addr the source callsign - * @param src_ssid the source SSID - * @param preamble_len the number of times that the AX.25 synchronization flags - * should be repeated in front of the frame. - * @param postamble_len the number of times that the AX.25 synchronization flags - * should be repeated at the end of the frame. - * @param scramble if set to true, G3RUH scrambling will be performed - * after bit stuffing - */ - static sptr - make (const std::string& dest_addr, uint8_t dest_ssid, - const std::string& src_addr, - uint8_t src_ssid, size_t preamble_len =16, - size_t postamble_len = 16, - bool scramble = true); - }; + /** + * AX.25 encoder block that supports the legacy hardware radios. + * + * The block takes as inputs blob PMT messages and generates a byte stream. + * Each output byte contains only one LSB, thus the output can be directly + * used for FM modulation. + * + * @param dest_addr the destination callsign + * @param dest_ssid the destination SSID + * @param src_addr the source callsign + * @param src_ssid the source SSID + * @param preamble_len the number of times that the AX.25 synchronization flags + * should be repeated in front of the frame. + * @param postamble_len the number of times that the AX.25 synchronization flags + * should be repeated at the end of the frame. + * @param scramble if set to true, G3RUH scrambling will be performed + * after bit stuffing + */ + static sptr + make(const std::string &dest_addr, uint8_t dest_ssid, + const std::string &src_addr, + uint8_t src_ssid, size_t preamble_len = 16, + size_t postamble_len = 16, + bool scramble = true); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_AX25_ENCODER_MB_H */ diff --git a/include/satnogs/base64.h b/include/satnogs/base64.h index 9910375..87afb8f 100644 --- a/include/satnogs/base64.h +++ b/include/satnogs/base64.h @@ -45,17 +45,17 @@ #include static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; static inline bool -is_base64 (unsigned char c) +is_base64(unsigned char c) { - return (isalnum (c) || (c == '+') || (c == '/')); + return (isalnum(c) || (c == '+') || (c == '/')); } static std::string -base64_encode (unsigned char const *bytes_to_encode, unsigned int in_len) +base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len) { std::string ret; int i = 0; @@ -68,32 +68,36 @@ base64_encode (unsigned char const *bytes_to_encode, unsigned int in_len) if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) - + ((char_array_3[1] & 0xf0) >> 4); + + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) - + ((char_array_3[2] & 0xc0) >> 6); + + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; - for (i = 0; (i < 4); i++) + for (i = 0; (i < 4); i++) { ret += base64_chars[char_array_4[i]]; + } i = 0; } } if (i) { - for (j = i; j < 3; j++) + for (j = i; j < 3; j++) { char_array_3[j] = '\0'; + } char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) - + ((char_array_3[1] & 0xf0) >> 4); + + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) - + ((char_array_3[2] & 0xc0) >> 6); + + ((char_array_3[2] & 0xc0) >> 6); - for (j = 0; (j < i + 1); j++) + for (j = 0; (j < i + 1); j++) { ret += base64_chars[char_array_4[j]]; + } - while ((i++ < 3)) + while ((i++ < 3)) { ret += '='; + } } @@ -102,9 +106,9 @@ base64_encode (unsigned char const *bytes_to_encode, unsigned int in_len) } static std::string -base64_decode (std::string const &encoded_string) +base64_decode(std::string const &encoded_string) { - size_t in_len = encoded_string.size (); + size_t in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; @@ -112,35 +116,39 @@ base64_decode (std::string const &encoded_string) std::string ret; while (in_len-- && (encoded_string[in_] != '=') - && is_base64 (encoded_string[in_])) { + && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i == 4) { - for (i = 0; i < 4; i++) - char_array_4[i] = base64_chars.find (char_array_4[i]) & 0xff; + for (i = 0; i < 4; i++) { + char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff; + } char_array_3[0] = (char_array_4[0] << 2) - + ((char_array_4[1] & 0x30) >> 4); + + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) - + ((char_array_4[2] & 0x3c) >> 2); + + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - for (i = 0; (i < 3); i++) + for (i = 0; (i < 3); i++) { ret += char_array_3[i]; + } i = 0; } } if (i) { - for (j = 0; j < i; j++) - char_array_4[j] = base64_chars.find (char_array_4[j]) & 0xff; + for (j = 0; j < i; j++) { + char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff; + } char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) - + ((char_array_4[2] & 0x3c) >> 2); + + ((char_array_4[2] & 0x3c) >> 2); - for (j = 0; (j < i - 1); j++) + for (j = 0; (j < i - 1); j++) { ret += char_array_3[j]; + } } return ret; diff --git a/include/satnogs/coarse_doppler_correction_cc.h b/include/satnogs/coarse_doppler_correction_cc.h index 2414e68..1df021b 100644 --- a/include/satnogs/coarse_doppler_correction_cc.h +++ b/include/satnogs/coarse_doppler_correction_cc.h @@ -24,39 +24,36 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief This block corrects the doppler effect between the ground - * station and the satellite in a coarse and very simplified way. - * Instead of changing the hardware center frequency, we use an NCO - * to digitally compensate the doppler effect. - * - * \ingroup satnogs - * - */ - class SATNOGS_API coarse_doppler_correction_cc : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief This block corrects the doppler effect between the ground + * station and the satellite in a coarse and very simplified way. + * Instead of changing the hardware center frequency, we use an NCO + * to digitally compensate the doppler effect. + * + * \ingroup satnogs + * + */ +class SATNOGS_API coarse_doppler_correction_cc : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /** - * The doppler correction block. The input is the complex signal at - * baseband as it comes from the SDR device. - * - * The message input \p freq receives periodically messages containing - * the predicted absolute frequency of the satellite at that specific time. - * @param target_freq the absolute frequency of the satellite - * @param sampling_rate the sampling rate of the signal - */ - static sptr - make (double target_freq, double sampling_rate); - }; + /** + * The doppler correction block. The input is the complex signal at + * baseband as it comes from the SDR device. + * + * The message input \p freq receives periodically messages containing + * the predicted absolute frequency of the satellite at that specific time. + * @param target_freq the absolute frequency of the satellite + * @param sampling_rate the sampling rate of the signal + */ + static sptr + make(double target_freq, double sampling_rate); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_COARSE_DOPPLER_CORRECTION_CC_H */ diff --git a/include/satnogs/convolutional_deinterleaver.h b/include/satnogs/convolutional_deinterleaver.h index aefbbcc..d050185 100644 --- a/include/satnogs/convolutional_deinterleaver.h +++ b/include/satnogs/convolutional_deinterleaver.h @@ -25,20 +25,17 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief <+description+> * */ -class SATNOGS_API convolutional_deinterleaver -{ +class SATNOGS_API convolutional_deinterleaver { public: - convolutional_deinterleaver (size_t branches, size_t M); - ~convolutional_deinterleaver (); + convolutional_deinterleaver(size_t branches, size_t M); + ~convolutional_deinterleaver(); uint8_t decode_bit(uint8_t b); diff --git a/include/satnogs/crc.h b/include/satnogs/crc.h index 4d290b6..d063f4e 100644 --- a/include/satnogs/crc.h +++ b/include/satnogs/crc.h @@ -23,17 +23,14 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * CRC class providing a range of different CRC calculation static methods * */ -class SATNOGS_API crc -{ +class SATNOGS_API crc { public: typedef enum crc_type { PDU = 0, diff --git a/include/satnogs/cw_encoder.h b/include/satnogs/cw_encoder.h index d21ed7b..fc25887 100644 --- a/include/satnogs/cw_encoder.h +++ b/include/satnogs/cw_encoder.h @@ -25,34 +25,31 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief CW encoder block, mainly for debugging and testing purposes. - * It accepts a CW word via a message source port and transmits the - * corresponding CW symbols. - * \ingroup satnogs - * - */ - class SATNOGS_API cw_encoder : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief CW encoder block, mainly for debugging and testing purposes. + * It accepts a CW word via a message source port and transmits the + * corresponding CW symbols. + * \ingroup satnogs + * + */ +class SATNOGS_API cw_encoder : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * \brief Return a shared_ptr to a new instance of satnogs::cw_encoder. - * @param samp_rate the sampling rate - * @param cw_freq the CW tone frequency - * @param wpm words per minute (WPM) - */ - static sptr - make (double samp_rate, double cw_freq = 700, size_t wpm = 20); - }; + /*! + * \brief Return a shared_ptr to a new instance of satnogs::cw_encoder. + * @param samp_rate the sampling rate + * @param cw_freq the CW tone frequency + * @param wpm words per minute (WPM) + */ + static sptr + make(double samp_rate, double cw_freq = 700, size_t wpm = 20); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_CW_ENCODER_H */ diff --git a/include/satnogs/cw_to_symbol.h b/include/satnogs/cw_to_symbol.h index 6a05bbf..5a2fd00 100644 --- a/include/satnogs/cw_to_symbol.h +++ b/include/satnogs/cw_to_symbol.h @@ -27,66 +27,63 @@ #define MIN_WPM 5 #define MAX_WPM 50 -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief The CW to Symbol block tries to translate the input signal - * into Morse symbols. The input signal should have been already properly - * filtered and processed. A possible DSP on the input signal may be the - * squared magnitude or the amplitude of the autocorrelation. Proper filtering - * that take cares possible spikes may drastically increase the performance - * of this block. - * - * \ingroup satnogs - */ - class SATNOGS_API cw_to_symbol : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief The CW to Symbol block tries to translate the input signal + * into Morse symbols. The input signal should have been already properly + * filtered and processed. A possible DSP on the input signal may be the + * squared magnitude or the amplitude of the autocorrelation. Proper filtering + * that take cares possible spikes may drastically increase the performance + * of this block. + * + * \ingroup satnogs + */ +class SATNOGS_API cw_to_symbol : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * The CW to Symbol block tries to translate the received signal - * power time-series into Morse symbols. - * - * The input stream is the energy of the signal in the time domain. - * For best results, a proper moving average filter should be applied - * before. - * - * Upon a successful recovery of a symbol it produces an appropriate - * asynchronous message that can directly be used by the Morse decoder - * block. - * - * @param sampling_rate the sampling rate of the signal - * @param threshold the activation threshold - * @param conf_level the confidence level, for the decisions made by - * the decoder. Higher values, means that the decoder would be more - * conservative, whereas lower may help in noisy environments but may - * trigger false alarms too, especially for the case of short pauses - * symbols - * - * @param wpm Morse code Words per Minute - * - * @param hysteresis this value represents the hysteresis of a possible - * filter used before the CW to Symbol block. For example if there is - * a moving average filter with x taps, the full power of the signal - * will be available after x samples. The total length of samples with - * maximum power will be 2*x less. Because the block searches for plateaus - * with proper durations, this filtering hysteresis should be known. - * If no such a filter is used, the hysteresis value should be set to zero. - */ - static cw_to_symbol::sptr - make (double sampling_rate, float threshold, float conf_level = 0.9, - size_t wpm = 20, - size_t hysteresis = 0); + /*! + * The CW to Symbol block tries to translate the received signal + * power time-series into Morse symbols. + * + * The input stream is the energy of the signal in the time domain. + * For best results, a proper moving average filter should be applied + * before. + * + * Upon a successful recovery of a symbol it produces an appropriate + * asynchronous message that can directly be used by the Morse decoder + * block. + * + * @param sampling_rate the sampling rate of the signal + * @param threshold the activation threshold + * @param conf_level the confidence level, for the decisions made by + * the decoder. Higher values, means that the decoder would be more + * conservative, whereas lower may help in noisy environments but may + * trigger false alarms too, especially for the case of short pauses + * symbols + * + * @param wpm Morse code Words per Minute + * + * @param hysteresis this value represents the hysteresis of a possible + * filter used before the CW to Symbol block. For example if there is + * a moving average filter with x taps, the full power of the signal + * will be available after x samples. The total length of samples with + * maximum power will be 2*x less. Because the block searches for plateaus + * with proper durations, this filtering hysteresis should be known. + * If no such a filter is used, the hysteresis value should be set to zero. + */ + static cw_to_symbol::sptr + make(double sampling_rate, float threshold, float conf_level = 0.9, + size_t wpm = 20, + size_t hysteresis = 0); - virtual void - set_act_threshold (float thrld) = 0; - }; + virtual void + set_act_threshold(float thrld) = 0; +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_CW_TO_SYMBOL_H */ diff --git a/include/satnogs/date.h b/include/satnogs/date.h index c1c8114..7f51e62 100644 --- a/include/satnogs/date.h +++ b/include/satnogs/date.h @@ -74,7 +74,7 @@ # pragma GCC diagnostic ignored "-Wpedantic" # endif # if __GNUC__ < 5 - // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers +// GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers # pragma GCC diagnostic ignored "-Wmissing-field-initializers" # endif #endif @@ -85,8 +85,7 @@ # pragma warning(disable : 4127) #endif -namespace date -{ +namespace date { //---------------+ // Configuration | @@ -164,21 +163,21 @@ namespace date // durations using days = std::chrono::duration - , std::chrono::hours::period>::type>; + , std::chrono::hours::period>::type>; using weeks = std::chrono::duration - , days::period>::type>; + , days::period>::type>; using years = std::chrono::duration - , days::period>::type>; + , days::period>::type>; using months = std::chrono::duration - >::type>; + >::type>; // time_point template - using sys_time = std::chrono::time_point; +using sys_time = std::chrono::time_point; using sys_days = sys_time; using sys_seconds = sys_time; @@ -186,16 +185,15 @@ using sys_seconds = sys_time; struct local_t {}; template - using local_time = std::chrono::time_point; +using local_time = std::chrono::time_point; using local_seconds = local_time; using local_days = local_time; // types -struct last_spec -{ - explicit last_spec() = default; +struct last_spec { + explicit last_spec() = default; }; class day; @@ -220,308 +218,301 @@ class year_month_weekday_last; // date composition operators -CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT; -CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT; +CONSTCD11 year_month operator/(const year &y, const month &m) NOEXCEPT; +CONSTCD11 year_month operator/(const year &y, int m) NOEXCEPT; -CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT; -CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT; -CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT; -CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT; -CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT; +CONSTCD11 month_day operator/(const day &d, const month &m) NOEXCEPT; +CONSTCD11 month_day operator/(const day &d, int m) NOEXCEPT; +CONSTCD11 month_day operator/(const month &m, const day &d) NOEXCEPT; +CONSTCD11 month_day operator/(const month &m, int d) NOEXCEPT; +CONSTCD11 month_day operator/(int m, const day &d) NOEXCEPT; -CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT; +CONSTCD11 month_day_last operator/(const month &m, last_spec) NOEXCEPT; CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT; -CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT; +CONSTCD11 month_day_last operator/(last_spec, const month &m) NOEXCEPT; CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT; -CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT; -CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT; -CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT; -CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT; +CONSTCD11 month_weekday operator/(const month &m, const weekday_indexed &wdi) NOEXCEPT; +CONSTCD11 month_weekday operator/(int m, const weekday_indexed &wdi) NOEXCEPT; +CONSTCD11 month_weekday operator/(const weekday_indexed &wdi, const month &m) NOEXCEPT; +CONSTCD11 month_weekday operator/(const weekday_indexed &wdi, int m) NOEXCEPT; -CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT; -CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT; -CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT; -CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT; +CONSTCD11 month_weekday_last operator/(const month &m, const weekday_last &wdl) NOEXCEPT; +CONSTCD11 month_weekday_last operator/(int m, const weekday_last &wdl) NOEXCEPT; +CONSTCD11 month_weekday_last operator/(const weekday_last &wdl, const month &m) NOEXCEPT; +CONSTCD11 month_weekday_last operator/(const weekday_last &wdl, int m) NOEXCEPT; -CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT; -CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT; -CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT; -CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT; -CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT; -CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT; +CONSTCD11 year_month_day operator/(const year_month &ym, const day &d) NOEXCEPT; +CONSTCD11 year_month_day operator/(const year_month &ym, int d) NOEXCEPT; +CONSTCD11 year_month_day operator/(const year &y, const month_day &md) NOEXCEPT; +CONSTCD11 year_month_day operator/(int y, const month_day &md) NOEXCEPT; +CONSTCD11 year_month_day operator/(const month_day &md, const year &y) NOEXCEPT; +CONSTCD11 year_month_day operator/(const month_day &md, int y) NOEXCEPT; CONSTCD11 - year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT; +year_month_day_last operator/(const year_month &ym, last_spec) NOEXCEPT; CONSTCD11 - year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT; +year_month_day_last operator/(const year &y, const month_day_last &mdl) NOEXCEPT; CONSTCD11 - year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT; +year_month_day_last operator/(int y, const month_day_last &mdl) NOEXCEPT; CONSTCD11 - year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT; +year_month_day_last operator/(const month_day_last &mdl, const year &y) NOEXCEPT; CONSTCD11 - year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT; +year_month_day_last operator/(const month_day_last &mdl, int y) NOEXCEPT; CONSTCD11 year_month_weekday -operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT; +operator/(const year_month &ym, const weekday_indexed &wdi) NOEXCEPT; CONSTCD11 year_month_weekday -operator/(const year& y, const month_weekday& mwd) NOEXCEPT; +operator/(const year &y, const month_weekday &mwd) NOEXCEPT; CONSTCD11 year_month_weekday -operator/(int y, const month_weekday& mwd) NOEXCEPT; +operator/(int y, const month_weekday &mwd) NOEXCEPT; CONSTCD11 year_month_weekday -operator/(const month_weekday& mwd, const year& y) NOEXCEPT; +operator/(const month_weekday &mwd, const year &y) NOEXCEPT; CONSTCD11 year_month_weekday -operator/(const month_weekday& mwd, int y) NOEXCEPT; +operator/(const month_weekday &mwd, int y) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT; +operator/(const year_month &ym, const weekday_last &wdl) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT; +operator/(const year &y, const month_weekday_last &mwdl) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator/(int y, const month_weekday_last& mwdl) NOEXCEPT; +operator/(int y, const month_weekday_last &mwdl) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT; +operator/(const month_weekday_last &mwdl, const year &y) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator/(const month_weekday_last& mwdl, int y) NOEXCEPT; +operator/(const month_weekday_last &mwdl, int y) NOEXCEPT; // Detailed interface // day -class day -{ - unsigned char d_; +class day { + unsigned char d_; public: - day() = default; - explicit CONSTCD11 day(unsigned d) NOEXCEPT; + day() = default; + explicit CONSTCD11 day(unsigned d) NOEXCEPT; - CONSTCD14 day& operator++() NOEXCEPT; - CONSTCD14 day operator++(int) NOEXCEPT; - CONSTCD14 day& operator--() NOEXCEPT; - CONSTCD14 day operator--(int) NOEXCEPT; + CONSTCD14 day &operator++() NOEXCEPT; + CONSTCD14 day operator++(int) NOEXCEPT; + CONSTCD14 day &operator--() NOEXCEPT; + CONSTCD14 day operator--(int) NOEXCEPT; - CONSTCD14 day& operator+=(const days& d) NOEXCEPT; - CONSTCD14 day& operator-=(const days& d) NOEXCEPT; + CONSTCD14 day &operator+=(const days &d) NOEXCEPT; + CONSTCD14 day &operator-=(const days &d) NOEXCEPT; - CONSTCD11 explicit operator unsigned() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 explicit operator unsigned() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT; -CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT; -CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT; -CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT; -CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT; -CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT; +CONSTCD11 bool operator==(const day &x, const day &y) NOEXCEPT; +CONSTCD11 bool operator!=(const day &x, const day &y) NOEXCEPT; +CONSTCD11 bool operator< (const day &x, const day &y) NOEXCEPT; +CONSTCD11 bool operator> (const day &x, const day &y) NOEXCEPT; +CONSTCD11 bool operator<=(const day &x, const day &y) NOEXCEPT; +CONSTCD11 bool operator>=(const day &x, const day &y) NOEXCEPT; -CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT; -CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT; -CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT; -CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT; +CONSTCD11 day operator+(const day &x, const days &y) NOEXCEPT; +CONSTCD11 day operator+(const days &x, const day &y) NOEXCEPT; +CONSTCD11 day operator-(const day &x, const days &y) NOEXCEPT; +CONSTCD11 days operator-(const day &x, const day &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const day& d); +std::basic_ostream & +operator<<(std::basic_ostream &os, const day &d); // month -class month -{ - unsigned char m_; +class month { + unsigned char m_; public: - month() = default; - explicit CONSTCD11 month(unsigned m) NOEXCEPT; + month() = default; + explicit CONSTCD11 month(unsigned m) NOEXCEPT; - CONSTCD14 month& operator++() NOEXCEPT; - CONSTCD14 month operator++(int) NOEXCEPT; - CONSTCD14 month& operator--() NOEXCEPT; - CONSTCD14 month operator--(int) NOEXCEPT; + CONSTCD14 month &operator++() NOEXCEPT; + CONSTCD14 month operator++(int) NOEXCEPT; + CONSTCD14 month &operator--() NOEXCEPT; + CONSTCD14 month operator--(int) NOEXCEPT; - CONSTCD14 month& operator+=(const months& m) NOEXCEPT; - CONSTCD14 month& operator-=(const months& m) NOEXCEPT; + CONSTCD14 month &operator+=(const months &m) NOEXCEPT; + CONSTCD14 month &operator-=(const months &m) NOEXCEPT; - CONSTCD11 explicit operator unsigned() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 explicit operator unsigned() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT; -CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT; -CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT; -CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT; -CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT; -CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT; +CONSTCD11 bool operator==(const month &x, const month &y) NOEXCEPT; +CONSTCD11 bool operator!=(const month &x, const month &y) NOEXCEPT; +CONSTCD11 bool operator< (const month &x, const month &y) NOEXCEPT; +CONSTCD11 bool operator> (const month &x, const month &y) NOEXCEPT; +CONSTCD11 bool operator<=(const month &x, const month &y) NOEXCEPT; +CONSTCD11 bool operator>=(const month &x, const month &y) NOEXCEPT; -CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT; -CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT; -CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT; -CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT; +CONSTCD14 month operator+(const month &x, const months &y) NOEXCEPT; +CONSTCD14 month operator+(const months &x, const month &y) NOEXCEPT; +CONSTCD14 month operator-(const month &x, const months &y) NOEXCEPT; +CONSTCD14 months operator-(const month &x, const month &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const month& m); +std::basic_ostream & +operator<<(std::basic_ostream &os, const month &m); // year -class year -{ - short y_; +class year { + short y_; public: - year() = default; - explicit CONSTCD11 year(int y) NOEXCEPT; + year() = default; + explicit CONSTCD11 year(int y) NOEXCEPT; - CONSTCD14 year& operator++() NOEXCEPT; - CONSTCD14 year operator++(int) NOEXCEPT; - CONSTCD14 year& operator--() NOEXCEPT; - CONSTCD14 year operator--(int) NOEXCEPT; + CONSTCD14 year &operator++() NOEXCEPT; + CONSTCD14 year operator++(int) NOEXCEPT; + CONSTCD14 year &operator--() NOEXCEPT; + CONSTCD14 year operator--(int) NOEXCEPT; - CONSTCD14 year& operator+=(const years& y) NOEXCEPT; - CONSTCD14 year& operator-=(const years& y) NOEXCEPT; + CONSTCD14 year &operator+=(const years &y) NOEXCEPT; + CONSTCD14 year &operator-=(const years &y) NOEXCEPT; - CONSTCD11 year operator-() const NOEXCEPT; - CONSTCD11 year operator+() const NOEXCEPT; + CONSTCD11 year operator-() const NOEXCEPT; + CONSTCD11 year operator+() const NOEXCEPT; - CONSTCD11 bool is_leap() const NOEXCEPT; + CONSTCD11 bool is_leap() const NOEXCEPT; - CONSTCD11 explicit operator int() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 explicit operator int() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; - static CONSTCD11 year min() NOEXCEPT { return year{-32767}; } - static CONSTCD11 year max() NOEXCEPT { return year{32767}; } + static CONSTCD11 year min() NOEXCEPT { return year{-32767}; } + static CONSTCD11 year max() NOEXCEPT { return year{32767}; } }; -CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT; -CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT; -CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT; -CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT; -CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT; -CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT; +CONSTCD11 bool operator==(const year &x, const year &y) NOEXCEPT; +CONSTCD11 bool operator!=(const year &x, const year &y) NOEXCEPT; +CONSTCD11 bool operator< (const year &x, const year &y) NOEXCEPT; +CONSTCD11 bool operator> (const year &x, const year &y) NOEXCEPT; +CONSTCD11 bool operator<=(const year &x, const year &y) NOEXCEPT; +CONSTCD11 bool operator>=(const year &x, const year &y) NOEXCEPT; -CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT; -CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT; -CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT; -CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT; +CONSTCD11 year operator+(const year &x, const years &y) NOEXCEPT; +CONSTCD11 year operator+(const years &x, const year &y) NOEXCEPT; +CONSTCD11 year operator-(const year &x, const years &y) NOEXCEPT; +CONSTCD11 years operator-(const year &x, const year &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const year& y); +std::basic_ostream & +operator<<(std::basic_ostream &os, const year &y); // weekday -class weekday -{ - unsigned char wd_; +class weekday { + unsigned char wd_; public: - weekday() = default; - explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; - CONSTCD14 weekday(const sys_days& dp) NOEXCEPT; - CONSTCD14 explicit weekday(const local_days& dp) NOEXCEPT; + weekday() = default; + explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; + CONSTCD14 weekday(const sys_days &dp) NOEXCEPT; + CONSTCD14 explicit weekday(const local_days &dp) NOEXCEPT; - CONSTCD14 weekday& operator++() NOEXCEPT; - CONSTCD14 weekday operator++(int) NOEXCEPT; - CONSTCD14 weekday& operator--() NOEXCEPT; - CONSTCD14 weekday operator--(int) NOEXCEPT; + CONSTCD14 weekday &operator++() NOEXCEPT; + CONSTCD14 weekday operator++(int) NOEXCEPT; + CONSTCD14 weekday &operator--() NOEXCEPT; + CONSTCD14 weekday operator--(int) NOEXCEPT; - CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT; - CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT; + CONSTCD14 weekday &operator+=(const days &d) NOEXCEPT; + CONSTCD14 weekday &operator-=(const days &d) NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; - CONSTCD11 unsigned c_encoding() const NOEXCEPT; - CONSTCD11 unsigned iso_encoding() const NOEXCEPT; + CONSTCD11 unsigned c_encoding() const NOEXCEPT; + CONSTCD11 unsigned iso_encoding() const NOEXCEPT; - CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; - CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT; + CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; + CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT; private: - static CONSTCD14 unsigned char weekday_from_days(int z) NOEXCEPT; + static CONSTCD14 unsigned char weekday_from_days(int z) NOEXCEPT; - friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; - friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; - friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; - template - friend std::basic_ostream& - operator<<(std::basic_ostream& os, const weekday& wd); - friend class weekday_indexed; + friend CONSTCD11 bool operator==(const weekday &x, const weekday &y) NOEXCEPT; + friend CONSTCD14 days operator-(const weekday &x, const weekday &y) NOEXCEPT; + friend CONSTCD14 weekday operator+(const weekday &x, const days &y) NOEXCEPT; + template + friend std::basic_ostream & + operator<<(std::basic_ostream &os, const weekday &wd); + friend class weekday_indexed; }; -CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; -CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT; +CONSTCD11 bool operator==(const weekday &x, const weekday &y) NOEXCEPT; +CONSTCD11 bool operator!=(const weekday &x, const weekday &y) NOEXCEPT; -CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; -CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT; -CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT; -CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; +CONSTCD14 weekday operator+(const weekday &x, const days &y) NOEXCEPT; +CONSTCD14 weekday operator+(const days &x, const weekday &y) NOEXCEPT; +CONSTCD14 weekday operator-(const weekday &x, const days &y) NOEXCEPT; +CONSTCD14 days operator-(const weekday &x, const weekday &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const weekday& wd); +std::basic_ostream & +operator<<(std::basic_ostream &os, const weekday &wd); // weekday_indexed -class weekday_indexed -{ - unsigned char wd_ : 4; - unsigned char index_ : 4; +class weekday_indexed { + unsigned char wd_ : 4; + unsigned char index_ : 4; public: - weekday_indexed() = default; - CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT; + weekday_indexed() = default; + CONSTCD11 weekday_indexed(const date::weekday &wd, unsigned index) NOEXCEPT; - CONSTCD11 date::weekday weekday() const NOEXCEPT; - CONSTCD11 unsigned index() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 date::weekday weekday() const NOEXCEPT; + CONSTCD11 unsigned index() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; -CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; +CONSTCD11 bool operator==(const weekday_indexed &x, const weekday_indexed &y) NOEXCEPT; +CONSTCD11 bool operator!=(const weekday_indexed &x, const weekday_indexed &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const weekday_indexed& wdi); +std::basic_ostream & +operator<<(std::basic_ostream &os, const weekday_indexed &wdi); // weekday_last -class weekday_last -{ - date::weekday wd_; +class weekday_last { + date::weekday wd_; public: - explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT; + explicit CONSTCD11 weekday_last(const date::weekday &wd) NOEXCEPT; - CONSTCD11 date::weekday weekday() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 date::weekday weekday() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT; -CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT; +CONSTCD11 bool operator==(const weekday_last &x, const weekday_last &y) NOEXCEPT; +CONSTCD11 bool operator!=(const weekday_last &x, const weekday_last &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const weekday_last& wdl); +std::basic_ostream & +operator<<(std::basic_ostream &os, const weekday_last &wdl); -namespace detail -{ +namespace detail { struct unspecified_month_disambiguator {}; @@ -529,429 +520,419 @@ struct unspecified_month_disambiguator {}; // year_month -class year_month -{ - date::year y_; - date::month m_; +class year_month { + date::year y_; + date::month m_; public: - year_month() = default; - CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT; + year_month() = default; + CONSTCD11 year_month(const date::year &y, const date::month &m) NOEXCEPT; - CONSTCD11 date::year year() const NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::year year() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; - template - CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT; - template - CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT; - CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT; - CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT; + template + CONSTCD14 year_month & operator+=(const months &dm) NOEXCEPT; + template + CONSTCD14 year_month & operator-=(const months &dm) NOEXCEPT; + CONSTCD14 year_month &operator+=(const years &dy) NOEXCEPT; + CONSTCD14 year_month &operator-=(const years &dy) NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT; -CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT; -CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT; -CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT; -CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT; -CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT; +CONSTCD11 bool operator==(const year_month &x, const year_month &y) NOEXCEPT; +CONSTCD11 bool operator!=(const year_month &x, const year_month &y) NOEXCEPT; +CONSTCD11 bool operator< (const year_month &x, const year_month &y) NOEXCEPT; +CONSTCD11 bool operator> (const year_month &x, const year_month &y) NOEXCEPT; +CONSTCD11 bool operator<=(const year_month &x, const year_month &y) NOEXCEPT; +CONSTCD11 bool operator>=(const year_month &x, const year_month &y) NOEXCEPT; template -CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT; +CONSTCD14 year_month operator+(const year_month &ym, const months &dm) NOEXCEPT; template -CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT; +CONSTCD14 year_month operator+(const months &dm, const year_month &ym) NOEXCEPT; template -CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT; +CONSTCD14 year_month operator-(const year_month &ym, const months &dm) NOEXCEPT; -CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT; -CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT; -CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT; -CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT; +CONSTCD11 months operator-(const year_month &x, const year_month &y) NOEXCEPT; +CONSTCD11 year_month operator+(const year_month &ym, const years &dy) NOEXCEPT; +CONSTCD11 year_month operator+(const years &dy, const year_month &ym) NOEXCEPT; +CONSTCD11 year_month operator-(const year_month &ym, const years &dy) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month& ym); +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month &ym); // month_day -class month_day -{ - date::month m_; - date::day d_; +class month_day { + date::month m_; + date::day d_; public: - month_day() = default; - CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT; + month_day() = default; + CONSTCD11 month_day(const date::month &m, const date::day &d) NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::day day() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::day day() const NOEXCEPT; - CONSTCD14 bool ok() const NOEXCEPT; + CONSTCD14 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT; -CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT; -CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT; -CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT; -CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT; -CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT; +CONSTCD11 bool operator==(const month_day &x, const month_day &y) NOEXCEPT; +CONSTCD11 bool operator!=(const month_day &x, const month_day &y) NOEXCEPT; +CONSTCD11 bool operator< (const month_day &x, const month_day &y) NOEXCEPT; +CONSTCD11 bool operator> (const month_day &x, const month_day &y) NOEXCEPT; +CONSTCD11 bool operator<=(const month_day &x, const month_day &y) NOEXCEPT; +CONSTCD11 bool operator>=(const month_day &x, const month_day &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_day& md); +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_day &md); // month_day_last -class month_day_last -{ - date::month m_; +class month_day_last { + date::month m_; public: - CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT; + CONSTCD11 explicit month_day_last(const date::month &m) NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT; -CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT; -CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT; -CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT; -CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT; -CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT; +CONSTCD11 bool operator==(const month_day_last &x, const month_day_last &y) NOEXCEPT; +CONSTCD11 bool operator!=(const month_day_last &x, const month_day_last &y) NOEXCEPT; +CONSTCD11 bool operator< (const month_day_last &x, const month_day_last &y) NOEXCEPT; +CONSTCD11 bool operator> (const month_day_last &x, const month_day_last &y) NOEXCEPT; +CONSTCD11 bool operator<=(const month_day_last &x, const month_day_last &y) NOEXCEPT; +CONSTCD11 bool operator>=(const month_day_last &x, const month_day_last &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_day_last& mdl); +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_day_last &mdl); // month_weekday -class month_weekday -{ - date::month m_; - date::weekday_indexed wdi_; +class month_weekday { + date::month m_; + date::weekday_indexed wdi_; public: - CONSTCD11 month_weekday(const date::month& m, - const date::weekday_indexed& wdi) NOEXCEPT; + CONSTCD11 month_weekday(const date::month &m, + const date::weekday_indexed &wdi) NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; -CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT; -CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT; +CONSTCD11 bool operator==(const month_weekday &x, const month_weekday &y) NOEXCEPT; +CONSTCD11 bool operator!=(const month_weekday &x, const month_weekday &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_weekday& mwd); +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_weekday &mwd); // month_weekday_last -class month_weekday_last -{ - date::month m_; - date::weekday_last wdl_; +class month_weekday_last { + date::month m_; + date::weekday_last wdl_; public: - CONSTCD11 month_weekday_last(const date::month& m, - const date::weekday_last& wd) NOEXCEPT; + CONSTCD11 month_weekday_last(const date::month &m, + const date::weekday_last &wd) NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 - bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; +bool operator==(const month_weekday_last &x, const month_weekday_last &y) NOEXCEPT; CONSTCD11 - bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; +bool operator!=(const month_weekday_last &x, const month_weekday_last &y) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_weekday_last& mwdl); +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_weekday_last &mwdl); // class year_month_day -class year_month_day -{ - date::year y_; - date::month m_; - date::day d_; +class year_month_day { + date::year y_; + date::month m_; + date::day d_; public: - year_month_day() = default; - CONSTCD11 year_month_day(const date::year& y, const date::month& m, - const date::day& d) NOEXCEPT; - CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT; + year_month_day() = default; + CONSTCD11 year_month_day(const date::year &y, const date::month &m, + const date::day &d) NOEXCEPT; + CONSTCD14 year_month_day(const year_month_day_last &ymdl) NOEXCEPT; - CONSTCD14 year_month_day(sys_days dp) NOEXCEPT; - CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT; + CONSTCD14 year_month_day(sys_days dp) NOEXCEPT; + CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT; - template - CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT; - template - CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT; - CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT; - CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT; + template + CONSTCD14 year_month_day & operator+=(const months &m) NOEXCEPT; + template + CONSTCD14 year_month_day & operator-=(const months &m) NOEXCEPT; + CONSTCD14 year_month_day &operator+=(const years &y) NOEXCEPT; + CONSTCD14 year_month_day &operator-=(const years &y) NOEXCEPT; - CONSTCD11 date::year year() const NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::day day() const NOEXCEPT; + CONSTCD11 date::year year() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::day day() const NOEXCEPT; - CONSTCD14 operator sys_days() const NOEXCEPT; - CONSTCD14 explicit operator local_days() const NOEXCEPT; - CONSTCD14 bool ok() const NOEXCEPT; + CONSTCD14 operator sys_days() const NOEXCEPT; + CONSTCD14 explicit operator local_days() const NOEXCEPT; + CONSTCD14 bool ok() const NOEXCEPT; private: - static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT; - CONSTCD14 days to_days() const NOEXCEPT; + static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT; + CONSTCD14 days to_days() const NOEXCEPT; }; -CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT; -CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT; -CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT; -CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT; -CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT; -CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT; +CONSTCD11 bool operator==(const year_month_day &x, const year_month_day &y) NOEXCEPT; +CONSTCD11 bool operator!=(const year_month_day &x, const year_month_day &y) NOEXCEPT; +CONSTCD11 bool operator< (const year_month_day &x, const year_month_day &y) NOEXCEPT; +CONSTCD11 bool operator> (const year_month_day &x, const year_month_day &y) NOEXCEPT; +CONSTCD11 bool operator<=(const year_month_day &x, const year_month_day &y) NOEXCEPT; +CONSTCD11 bool operator>=(const year_month_day &x, const year_month_day &y) NOEXCEPT; template -CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT; +CONSTCD14 year_month_day operator+(const year_month_day &ymd, const months &dm) NOEXCEPT; template -CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT; +CONSTCD14 year_month_day operator+(const months &dm, const year_month_day &ymd) NOEXCEPT; template -CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT; -CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT; -CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT; -CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT; +CONSTCD14 year_month_day operator-(const year_month_day &ymd, const months &dm) NOEXCEPT; +CONSTCD11 year_month_day operator+(const year_month_day &ymd, const years &dy) NOEXCEPT; +CONSTCD11 year_month_day operator+(const years &dy, const year_month_day &ymd) NOEXCEPT; +CONSTCD11 year_month_day operator-(const year_month_day &ymd, const years &dy) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_day& ymd); +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_day &ymd); // year_month_day_last -class year_month_day_last -{ - date::year y_; - date::month_day_last mdl_; +class year_month_day_last { + date::year y_; + date::month_day_last mdl_; public: - CONSTCD11 year_month_day_last(const date::year& y, - const date::month_day_last& mdl) NOEXCEPT; + CONSTCD11 year_month_day_last(const date::year &y, + const date::month_day_last &mdl) NOEXCEPT; - template - CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT; - template - CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT; - CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT; - CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT; + template + CONSTCD14 year_month_day_last & operator+=(const months &m) NOEXCEPT; + template + CONSTCD14 year_month_day_last & operator-=(const months &m) NOEXCEPT; + CONSTCD14 year_month_day_last &operator+=(const years &y) NOEXCEPT; + CONSTCD14 year_month_day_last &operator-=(const years &y) NOEXCEPT; - CONSTCD11 date::year year() const NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT; - CONSTCD14 date::day day() const NOEXCEPT; + CONSTCD11 date::year year() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT; + CONSTCD14 date::day day() const NOEXCEPT; - CONSTCD14 operator sys_days() const NOEXCEPT; - CONSTCD14 explicit operator local_days() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD14 operator sys_days() const NOEXCEPT; + CONSTCD14 explicit operator local_days() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 - bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; +bool operator==(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT; CONSTCD11 - bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; +bool operator!=(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT; CONSTCD11 - bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; +bool operator< (const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT; CONSTCD11 - bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; +bool operator> (const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT; CONSTCD11 - bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; +bool operator<=(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT; CONSTCD11 - bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; +bool operator>=(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT; template CONSTCD14 year_month_day_last -operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; +operator+(const year_month_day_last &ymdl, const months &dm) NOEXCEPT; template CONSTCD14 year_month_day_last -operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT; +operator+(const months &dm, const year_month_day_last &ymdl) NOEXCEPT; CONSTCD11 year_month_day_last -operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; +operator+(const year_month_day_last &ymdl, const years &dy) NOEXCEPT; CONSTCD11 year_month_day_last -operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT; +operator+(const years &dy, const year_month_day_last &ymdl) NOEXCEPT; template CONSTCD14 year_month_day_last -operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; +operator-(const year_month_day_last &ymdl, const months &dm) NOEXCEPT; CONSTCD11 year_month_day_last -operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; +operator-(const year_month_day_last &ymdl, const years &dy) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_day_last& ymdl); +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_day_last &ymdl); // year_month_weekday -class year_month_weekday -{ - date::year y_; - date::month m_; - date::weekday_indexed wdi_; +class year_month_weekday { + date::year y_; + date::month m_; + date::weekday_indexed wdi_; public: - year_month_weekday() = default; - CONSTCD11 year_month_weekday(const date::year& y, const date::month& m, - const date::weekday_indexed& wdi) NOEXCEPT; - CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT; - CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT; + year_month_weekday() = default; + CONSTCD11 year_month_weekday(const date::year &y, const date::month &m, + const date::weekday_indexed &wdi) NOEXCEPT; + CONSTCD14 year_month_weekday(const sys_days &dp) NOEXCEPT; + CONSTCD14 explicit year_month_weekday(const local_days &dp) NOEXCEPT; - template - CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT; - template - CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT; - CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT; - CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT; + template + CONSTCD14 year_month_weekday & operator+=(const months &m) NOEXCEPT; + template + CONSTCD14 year_month_weekday & operator-=(const months &m) NOEXCEPT; + CONSTCD14 year_month_weekday &operator+=(const years &y) NOEXCEPT; + CONSTCD14 year_month_weekday &operator-=(const years &y) NOEXCEPT; - CONSTCD11 date::year year() const NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::weekday weekday() const NOEXCEPT; - CONSTCD11 unsigned index() const NOEXCEPT; - CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; + CONSTCD11 date::year year() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::weekday weekday() const NOEXCEPT; + CONSTCD11 unsigned index() const NOEXCEPT; + CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; - CONSTCD14 operator sys_days() const NOEXCEPT; - CONSTCD14 explicit operator local_days() const NOEXCEPT; - CONSTCD14 bool ok() const NOEXCEPT; + CONSTCD14 operator sys_days() const NOEXCEPT; + CONSTCD14 explicit operator local_days() const NOEXCEPT; + CONSTCD14 bool ok() const NOEXCEPT; private: - static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT; - CONSTCD14 days to_days() const NOEXCEPT; + static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT; + CONSTCD14 days to_days() const NOEXCEPT; }; CONSTCD11 - bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; +bool operator==(const year_month_weekday &x, const year_month_weekday &y) NOEXCEPT; CONSTCD11 - bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; +bool operator!=(const year_month_weekday &x, const year_month_weekday &y) NOEXCEPT; template CONSTCD14 year_month_weekday -operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; +operator+(const year_month_weekday &ymwd, const months &dm) NOEXCEPT; template CONSTCD14 year_month_weekday -operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT; +operator+(const months &dm, const year_month_weekday &ymwd) NOEXCEPT; CONSTCD11 year_month_weekday -operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; +operator+(const year_month_weekday &ymwd, const years &dy) NOEXCEPT; CONSTCD11 year_month_weekday -operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT; +operator+(const years &dy, const year_month_weekday &ymwd) NOEXCEPT; template CONSTCD14 year_month_weekday -operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; +operator-(const year_month_weekday &ymwd, const months &dm) NOEXCEPT; CONSTCD11 year_month_weekday -operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; +operator-(const year_month_weekday &ymwd, const years &dy) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi); +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_weekday &ymwdi); // year_month_weekday_last -class year_month_weekday_last -{ - date::year y_; - date::month m_; - date::weekday_last wdl_; +class year_month_weekday_last { + date::year y_; + date::month m_; + date::weekday_last wdl_; public: - CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m, - const date::weekday_last& wdl) NOEXCEPT; + CONSTCD11 year_month_weekday_last(const date::year &y, const date::month &m, + const date::weekday_last &wdl) NOEXCEPT; - template - CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT; - template - CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT; - CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT; - CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT; + template + CONSTCD14 year_month_weekday_last & operator+=(const months &m) NOEXCEPT; + template + CONSTCD14 year_month_weekday_last & operator-=(const months &m) NOEXCEPT; + CONSTCD14 year_month_weekday_last &operator+=(const years &y) NOEXCEPT; + CONSTCD14 year_month_weekday_last &operator-=(const years &y) NOEXCEPT; - CONSTCD11 date::year year() const NOEXCEPT; - CONSTCD11 date::month month() const NOEXCEPT; - CONSTCD11 date::weekday weekday() const NOEXCEPT; - CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; + CONSTCD11 date::year year() const NOEXCEPT; + CONSTCD11 date::month month() const NOEXCEPT; + CONSTCD11 date::weekday weekday() const NOEXCEPT; + CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; - CONSTCD14 operator sys_days() const NOEXCEPT; - CONSTCD14 explicit operator local_days() const NOEXCEPT; - CONSTCD11 bool ok() const NOEXCEPT; + CONSTCD14 operator sys_days() const NOEXCEPT; + CONSTCD14 explicit operator local_days() const NOEXCEPT; + CONSTCD11 bool ok() const NOEXCEPT; private: - CONSTCD14 days to_days() const NOEXCEPT; + CONSTCD14 days to_days() const NOEXCEPT; }; CONSTCD11 bool -operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; +operator==(const year_month_weekday_last &x, const year_month_weekday_last &y) NOEXCEPT; CONSTCD11 bool -operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; +operator!=(const year_month_weekday_last &x, const year_month_weekday_last &y) NOEXCEPT; template CONSTCD14 year_month_weekday_last -operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; +operator+(const year_month_weekday_last &ymwdl, const months &dm) NOEXCEPT; template CONSTCD14 year_month_weekday_last -operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT; +operator+(const months &dm, const year_month_weekday_last &ymwdl) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; +operator+(const year_month_weekday_last &ymwdl, const years &dy) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT; +operator+(const years &dy, const year_month_weekday_last &ymwdl) NOEXCEPT; template CONSTCD14 year_month_weekday_last -operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; +operator-(const year_month_weekday_last &ymwdl, const months &dm) NOEXCEPT; CONSTCD11 year_month_weekday_last -operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; +operator-(const year_month_weekday_last &ymwdl, const years &dy) NOEXCEPT; template -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl); +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_weekday_last &ymwdl); #if !defined(_MSC_VER) || (_MSC_VER >= 1900) -inline namespace literals -{ +inline namespace literals { CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT; CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT; @@ -984,15 +965,15 @@ CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT; template > struct is_clock - : std::false_type -{}; + : std::false_type { +}; template struct is_clock> - : std::true_type -{}; + typename T::duration, typename T::time_point, + decltype(T::is_steady)>> + : std::true_type { + }; #endif // HAS_VOID_T @@ -1004,87 +985,86 @@ struct is_clock> -class save_istream -{ +class save_istream { protected: - std::basic_ios& is_; - CharT fill_; - std::ios::fmtflags flags_; - std::streamsize width_; - std::basic_ostream* tie_; - std::locale loc_; + std::basic_ios &is_; + CharT fill_; + std::ios::fmtflags flags_; + std::streamsize width_; + std::basic_ostream *tie_; + std::locale loc_; public: - ~save_istream() - { - is_.fill(fill_); - is_.flags(flags_); - is_.width(width_); - is_.imbue(loc_); - is_.tie(tie_); + ~save_istream() + { + is_.fill(fill_); + is_.flags(flags_); + is_.width(width_); + is_.imbue(loc_); + is_.tie(tie_); + } + + save_istream(const save_istream &) = delete; + save_istream &operator=(const save_istream &) = delete; + + explicit save_istream(std::basic_ios &is) + : is_(is) + , fill_(is.fill()) + , flags_(is.flags()) + , width_(is.width(0)) + , tie_(is.tie(nullptr)) + , loc_(is.getloc()) + { + if (tie_ != nullptr) { + tie_->flush(); } - - save_istream(const save_istream&) = delete; - save_istream& operator=(const save_istream&) = delete; - - explicit save_istream(std::basic_ios& is) - : is_(is) - , fill_(is.fill()) - , flags_(is.flags()) - , width_(is.width(0)) - , tie_(is.tie(nullptr)) - , loc_(is.getloc()) - { - if (tie_ != nullptr) - tie_->flush(); - } + } }; template> class save_ostream - : private save_istream -{ + : private save_istream { public: - ~save_ostream() - { - if ((this->flags_ & std::ios::unitbuf) && + ~save_ostream() + { + if ((this->flags_ & std::ios::unitbuf) && #if HAS_UNCAUGHT_EXCEPTIONS - std::uncaught_exceptions() == 0 && + std::uncaught_exceptions() == 0 && #else - !std::uncaught_exception() && + !std::uncaught_exception() && #endif - this->is_.good()) - this->is_.rdbuf()->pubsync(); + this->is_.good()) { + this->is_.rdbuf()->pubsync(); } + } - save_ostream(const save_ostream&) = delete; - save_ostream& operator=(const save_ostream&) = delete; + save_ostream(const save_ostream &) = delete; + save_ostream &operator=(const save_ostream &) = delete; - explicit save_ostream(std::basic_ios& os) - : save_istream(os) - { - } + explicit save_ostream(std::basic_ios &os) + : save_istream(os) + { + } }; template -struct choose_trunc_type -{ - static const int digits = std::numeric_limits::digits; - using type = typename std::conditional - < - digits < 32, - std::int32_t, - typename std::conditional - < - digits < 64, - std::int64_t, +struct choose_trunc_type { + static const int digits = std::numeric_limits::digits; + using type = typename std::conditional + < + digits < 32, + std::int32_t, + typename std::conditional + < + digits < 64, + std::int64_t, #ifdef __SIZEOF_INT128__ - __int128 + __int128 #else - std::int64_t + std::int64_t #endif - >::type - >::type; + >::type + >::type; }; template @@ -1092,12 +1072,11 @@ CONSTCD11 inline typename std::enable_if < - !std::chrono::treat_as_floating_point::value, - T +!std::chrono::treat_as_floating_point::value, +T >::type -trunc(T t) NOEXCEPT -{ - return t; +trunc(T t) NOEXCEPT { + return t; } template @@ -1105,73 +1084,67 @@ CONSTCD14 inline typename std::enable_if < - std::chrono::treat_as_floating_point::value, +std::chrono::treat_as_floating_point::value, T ->::type -trunc(T t) NOEXCEPT -{ - using std::numeric_limits; - using I = typename choose_trunc_type::type; - CONSTDATA auto digits = numeric_limits::digits; - static_assert(digits < numeric_limits::digits, ""); - CONSTDATA auto max = I{1} << (digits-1); - CONSTDATA auto min = -max; - const auto negative = t < T{0}; - if (min <= t && t <= max && t != 0 && t == t) - { - t = static_cast(static_cast(t)); - if (t == 0 && negative) - t = -t; + >::type +trunc(T t) NOEXCEPT { + using std::numeric_limits; + using I = typename choose_trunc_type::type; + CONSTDATA auto digits = numeric_limits::digits; + static_assert(digits < numeric_limits::digits, ""); + CONSTDATA auto max = I{1} << (digits - 1); + CONSTDATA auto min = -max; + const auto negative = t < T{0}; + if (min <= t && t <= max && t != 0 && t == t) + { + t = static_cast(static_cast(t)); + if (t == 0 && negative) { + t = -t; } - return t; + } + return t; } template -struct static_gcd -{ - static const std::intmax_t value = static_gcd::value; +struct static_gcd { + static const std::intmax_t value = static_gcd < Yp, Xp % Yp >::value; }; template -struct static_gcd -{ - static const std::intmax_t value = Xp; +struct static_gcd { + static const std::intmax_t value = Xp; }; template <> -struct static_gcd<0, 0> -{ - static const std::intmax_t value = 1; +struct static_gcd<0, 0> { + static const std::intmax_t value = 1; }; template -struct no_overflow -{ +struct no_overflow { private: - static const std::intmax_t gcd_n1_n2 = static_gcd::value; - static const std::intmax_t gcd_d1_d2 = static_gcd::value; - static const std::intmax_t n1 = R1::num / gcd_n1_n2; - static const std::intmax_t d1 = R1::den / gcd_d1_d2; - static const std::intmax_t n2 = R2::num / gcd_n1_n2; - static const std::intmax_t d2 = R2::den / gcd_d1_d2; - static const std::intmax_t max = INTMAX_MAX; + static const std::intmax_t gcd_n1_n2 = static_gcd::value; + static const std::intmax_t gcd_d1_d2 = static_gcd::value; + static const std::intmax_t n1 = R1::num / gcd_n1_n2; + static const std::intmax_t d1 = R1::den / gcd_d1_d2; + static const std::intmax_t n2 = R2::num / gcd_n1_n2; + static const std::intmax_t d2 = R2::den / gcd_d1_d2; + static const std::intmax_t max = INTMAX_MAX; - template - struct mul // overflow == false - { - static const std::intmax_t value = Xp * Yp; - }; + template + struct mul { // overflow == false + static const std::intmax_t value = Xp * Yp; + }; - template - struct mul - { - static const std::intmax_t value = 1; - }; + template + struct mul { + static const std::intmax_t value = 1; + }; public: - static const bool value = (n1 <= max / d2) && (n2 <= max / d1); - typedef std::ratio::value, - mul::value> type; + static const bool value = (n1 <= max / d2) && (n2 <= max / d1); + typedef std::ratio < mul < n1, d2, !value >::value, + mul < n2, d1, !value >::value > type; }; } // detail @@ -1182,12 +1155,12 @@ CONSTCD11 inline typename std::enable_if < - detail::no_overflow::value, - To ->::type -trunc(const std::chrono::duration& d) +detail::no_overflow::value, + To + >::type + trunc(const std::chrono::duration &d) { - return To{detail::trunc(std::chrono::duration_cast(d).count())}; + return To{detail::trunc(std::chrono::duration_cast(d).count())}; } template @@ -1195,15 +1168,15 @@ CONSTCD11 inline typename std::enable_if < - !detail::no_overflow::value, - To +!detail::no_overflow::value, +To >::type -trunc(const std::chrono::duration& d) +trunc(const std::chrono::duration &d) { - using std::chrono::duration_cast; - using std::chrono::duration; - using rep = typename std::common_type::type; - return To{detail::trunc(duration_cast(duration_cast>(d)).count())}; + using std::chrono::duration_cast; + using std::chrono::duration; + using rep = typename std::common_type::type; + return To{detail::trunc(duration_cast(duration_cast>(d)).count())}; } #ifndef HAS_CHRONO_ROUNDING @@ -1226,15 +1199,15 @@ CONSTCD14 inline typename std::enable_if < - detail::no_overflow::value, - To ->::type -floor(const std::chrono::duration& d) +detail::no_overflow::value, + To + >::type + floor(const std::chrono::duration &d) { - auto t = trunc(d); - if (t > d) - return t - To{1}; - return t; + auto t = trunc(d); + if (t > d) + return t - To{1}; + return t; } template @@ -1242,13 +1215,13 @@ CONSTCD14 inline typename std::enable_if < - !detail::no_overflow::value, - To +!detail::no_overflow::value, +To >::type -floor(const std::chrono::duration& d) +floor(const std::chrono::duration &d) { - using rep = typename std::common_type::type; - return floor(floor>(d)); + using rep = typename std::common_type::type; + return floor(floor>(d)); } // round to nearest, to even on tie @@ -1256,23 +1229,23 @@ template CONSTCD14 inline To -round(const std::chrono::duration& d) +round(const std::chrono::duration &d) { - auto t0 = floor(d); - auto t1 = t0 + To{1}; - if (t1 == To{0} && t0 < To{0}) - t1 = -t1; - auto diff0 = d - t0; - auto diff1 = t1 - d; - if (diff0 == diff1) - { - if (t0 - trunc(t0/2)*2 == To{0}) - return t0; - return t1; - } - if (diff0 < diff1) - return t0; + auto t0 = floor(d); + auto t1 = t0 + To{1}; + if (t1 == To{0} && t0 < To{0}) + t1 = -t1; + auto diff0 = d - t0; + auto diff1 = t1 - d; + if (diff0 == diff1) { + if (t0 - trunc(t0 / 2) * 2 == To{0}) + return t0; return t1; + } + if (diff0 < diff1) { + return t0; + } + return t1; } // round up @@ -1280,24 +1253,24 @@ template CONSTCD14 inline To -ceil(const std::chrono::duration& d) +ceil(const std::chrono::duration &d) { - auto t = trunc(d); - if (t < d) - return t + To{1}; - return t; + auto t = trunc(d); + if (t < d) + return t + To{1}; + return t; } template ::is_signed - >::type> + std::numeric_limits::is_signed + >::type> CONSTCD11 std::chrono::duration abs(std::chrono::duration d) { - return d >= d.zero() ? d : -d; + return d >= d.zero() ? d : -d; } // round down @@ -1305,10 +1278,10 @@ template CONSTCD11 inline std::chrono::time_point -floor(const std::chrono::time_point& tp) +floor(const std::chrono::time_point &tp) { - using std::chrono::time_point; - return time_point{date::floor(tp.time_since_epoch())}; + using std::chrono::time_point; + return time_point {date::floor(tp.time_since_epoch())}; } // round to nearest, to even on tie @@ -1316,10 +1289,10 @@ template CONSTCD11 inline std::chrono::time_point -round(const std::chrono::time_point& tp) +round(const std::chrono::time_point &tp) { - using std::chrono::time_point; - return time_point{round(tp.time_since_epoch())}; + using std::chrono::time_point; + return time_point {round(tp.time_since_epoch())}; } // round up @@ -1327,10 +1300,10 @@ template CONSTCD11 inline std::chrono::time_point -ceil(const std::chrono::time_point& tp) +ceil(const std::chrono::time_point &tp) { - using std::chrono::time_point; - return time_point{ceil(tp.time_since_epoch())}; + using std::chrono::time_point; + return time_point {ceil(tp.time_since_epoch())}; } #else // HAS_CHRONO_ROUNDING == 1 @@ -1347,371 +1320,366 @@ template CONSTCD11 inline std::chrono::time_point -trunc(const std::chrono::time_point& tp) +trunc(const std::chrono::time_point &tp) { - using std::chrono::time_point; - return time_point{trunc(tp.time_since_epoch())}; + using std::chrono::time_point; + return time_point {trunc(tp.time_since_epoch())}; } // day -CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast(d)) {} -CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;} +CONSTCD11 inline day::day(unsigned d) NOEXCEPT : +d_(static_cast(d)) {} +CONSTCD14 inline day &day::operator++() NOEXCEPT {++d_; return *this;} CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} -CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;} +CONSTCD14 inline day &day::operator--() NOEXCEPT {--d_; return *this;} CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} -CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;} -CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;} -CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;} -CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;} - -CONSTCD11 -inline -bool -operator==(const day& x, const day& y) NOEXCEPT +CONSTCD14 inline day &day::operator+=(const days &d) NOEXCEPT {*this = *this + d; return *this;} +CONSTCD14 inline day &day::operator-=(const days &d) NOEXCEPT {*this = *this - d; return *this;} +CONSTCD11 inline day::operator unsigned() const NOEXCEPT { - return static_cast(x) == static_cast(y); + return d_; +} +CONSTCD11 inline bool day::ok() const NOEXCEPT +{ + return 1 <= d_ && d_ <= 31; } CONSTCD11 inline bool -operator!=(const day& x, const day& y) NOEXCEPT -{ - return !(x == y); +operator==(const day &x, const day &y) NOEXCEPT { + return static_cast(x) == static_cast(y); } CONSTCD11 inline bool -operator<(const day& x, const day& y) NOEXCEPT -{ - return static_cast(x) < static_cast(y); +operator!=(const day &x, const day &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator>(const day& x, const day& y) NOEXCEPT -{ - return y < x; +operator<(const day &x, const day &y) NOEXCEPT { + return static_cast(x) < static_cast(y); } CONSTCD11 inline bool -operator<=(const day& x, const day& y) NOEXCEPT -{ - return !(y < x); +operator>(const day &x, const day &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator>=(const day& x, const day& y) NOEXCEPT -{ - return !(x < y); +operator<=(const day &x, const day &y) NOEXCEPT { + return !(y < x); +} + +CONSTCD11 +inline +bool +operator>=(const day &x, const day &y) NOEXCEPT { + return !(x < y); } CONSTCD11 inline days -operator-(const day& x, const day& y) NOEXCEPT -{ - return days{static_cast(static_cast(x) - - static_cast(y))}; +operator-(const day &x, const day &y) NOEXCEPT { + return days{ + static_cast(static_cast(x) + - static_cast(y))}; } CONSTCD11 inline day -operator+(const day& x, const days& y) NOEXCEPT -{ - return day{static_cast(x) + static_cast(y.count())}; +operator+(const day &x, const days &y) NOEXCEPT { + return day{static_cast(x) + static_cast(y.count())}; } CONSTCD11 inline day -operator+(const days& x, const day& y) NOEXCEPT -{ - return y + x; +operator+(const days &x, const day &y) NOEXCEPT { + return y + x; } CONSTCD11 inline day -operator-(const day& x, const days& y) NOEXCEPT -{ - return x + -y; +operator-(const day &x, const days &y) NOEXCEPT { + return x + -y; } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const day& d) +std::basic_ostream & +operator<<(std::basic_ostream &os, const day &d) { - detail::save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(2); - os << static_cast(d); - if (!d.ok()) - os << " is not a valid day"; - return os; + detail::save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(2); + os << static_cast(d); + if (!d.ok()) { + os << " is not a valid day"; + } + return os; } // month -CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast(m)) {} -CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;} +CONSTCD11 inline month::month(unsigned m) NOEXCEPT : +m_(static_cast(m)) {} +CONSTCD14 inline month &month::operator++() NOEXCEPT {*this += months{1}; return *this;} CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} -CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;} +CONSTCD14 inline month &month::operator--() NOEXCEPT {*this -= months{1}; return *this;} CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} CONSTCD14 inline -month& -month::operator+=(const months& m) NOEXCEPT -{ - *this = *this + m; - return *this; +month & +month::operator+=(const months &m) NOEXCEPT { + *this = *this + m; + return *this; } CONSTCD14 inline -month& -month::operator-=(const months& m) NOEXCEPT -{ - *this = *this - m; - return *this; +month & +month::operator-=(const months &m) NOEXCEPT { + *this = *this - m; + return *this; } -CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;} -CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;} - -CONSTCD11 -inline -bool -operator==(const month& x, const month& y) NOEXCEPT +CONSTCD11 inline month::operator unsigned() const NOEXCEPT { - return static_cast(x) == static_cast(y); + return m_; +} +CONSTCD11 inline bool month::ok() const NOEXCEPT +{ + return 1 <= m_ && m_ <= 12; } CONSTCD11 inline bool -operator!=(const month& x, const month& y) NOEXCEPT -{ - return !(x == y); +operator==(const month &x, const month &y) NOEXCEPT { + return static_cast(x) == static_cast(y); } CONSTCD11 inline bool -operator<(const month& x, const month& y) NOEXCEPT -{ - return static_cast(x) < static_cast(y); +operator!=(const month &x, const month &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator>(const month& x, const month& y) NOEXCEPT -{ - return y < x; +operator<(const month &x, const month &y) NOEXCEPT { + return static_cast(x) < static_cast(y); } CONSTCD11 inline bool -operator<=(const month& x, const month& y) NOEXCEPT -{ - return !(y < x); +operator>(const month &x, const month &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator>=(const month& x, const month& y) NOEXCEPT -{ - return !(x < y); +operator<=(const month &x, const month &y) NOEXCEPT { + return !(y < x); +} + +CONSTCD11 +inline +bool +operator>=(const month &x, const month &y) NOEXCEPT { + return !(x < y); } CONSTCD14 inline months -operator-(const month& x, const month& y) NOEXCEPT -{ - auto const d = static_cast(x) - static_cast(y); - return months(d <= 11 ? d : d + 12); +operator-(const month &x, const month &y) NOEXCEPT { + auto const d = static_cast(x) - static_cast(y); + return months(d <= 11 ? d : d + 12); } CONSTCD14 inline month -operator+(const month& x, const months& y) NOEXCEPT -{ - auto const mu = static_cast(static_cast(x)) + (y.count() - 1); - auto const yr = (mu >= 0 ? mu : mu-11) / 12; - return month{static_cast(mu - yr * 12 + 1)}; +operator+(const month &x, const months &y) NOEXCEPT { + auto const mu = static_cast(static_cast(x)) + (y.count() - 1); + auto const yr = (mu >= 0 ? mu : mu - 11) / 12; + return month{static_cast(mu - yr * 12 + 1)}; } CONSTCD14 inline month -operator+(const months& x, const month& y) NOEXCEPT -{ - return y + x; +operator+(const months &x, const month &y) NOEXCEPT { + return y + x; } CONSTCD14 inline month -operator-(const month& x, const months& y) NOEXCEPT -{ - return x + -y; +operator-(const month &x, const months &y) NOEXCEPT { + return x + -y; } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const month& m) +std::basic_ostream & +operator<<(std::basic_ostream &os, const month &m) { - if (m.ok()) - { - CharT fmt[] = {'%', 'b', 0}; - os << format(os.getloc(), fmt, m); - } - else - os << static_cast(m) << " is not a valid month"; - return os; + if (m.ok()) { + CharT fmt[] = {'%', 'b', 0}; + os << format(os.getloc(), fmt, m); + } + else { + os << static_cast(m) << " is not a valid month"; + } + return os; } // year -CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast(y)) {} -CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;} +CONSTCD11 inline year::year(int y) NOEXCEPT : +y_(static_cast(y)) {} +CONSTCD14 inline year &year::operator++() NOEXCEPT {++y_; return *this;} CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} -CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;} +CONSTCD14 inline year &year::operator--() NOEXCEPT {--y_; return *this;} CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} -CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;} -CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;} -CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};} -CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;} +CONSTCD14 inline year &year::operator+=(const years &y) NOEXCEPT {*this = *this + y; return *this;} +CONSTCD14 inline year &year::operator-=(const years &y) NOEXCEPT {*this = *this - y; return *this;} +CONSTCD11 inline year year::operator-() const NOEXCEPT +{ + return year{-y_}; +} +CONSTCD11 inline year year::operator+() const NOEXCEPT +{ + return *this; +} CONSTCD11 inline bool year::is_leap() const NOEXCEPT { - return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0); + return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0); } -CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} +CONSTCD11 inline year::operator int() const NOEXCEPT +{ + return y_; +} CONSTCD11 inline bool year::ok() const NOEXCEPT { - return y_ != std::numeric_limits::min(); + return y_ != std::numeric_limits::min(); } CONSTCD11 inline bool -operator==(const year& x, const year& y) NOEXCEPT -{ - return static_cast(x) == static_cast(y); +operator==(const year &x, const year &y) NOEXCEPT { + return static_cast(x) == static_cast(y); } CONSTCD11 inline bool -operator!=(const year& x, const year& y) NOEXCEPT -{ - return !(x == y); +operator!=(const year &x, const year &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator<(const year& x, const year& y) NOEXCEPT -{ - return static_cast(x) < static_cast(y); +operator<(const year &x, const year &y) NOEXCEPT { + return static_cast(x) < static_cast(y); } CONSTCD11 inline bool -operator>(const year& x, const year& y) NOEXCEPT -{ - return y < x; +operator>(const year &x, const year &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator<=(const year& x, const year& y) NOEXCEPT -{ - return !(y < x); +operator<=(const year &x, const year &y) NOEXCEPT { + return !(y < x); } CONSTCD11 inline bool -operator>=(const year& x, const year& y) NOEXCEPT -{ - return !(x < y); +operator>=(const year &x, const year &y) NOEXCEPT { + return !(x < y); } CONSTCD11 inline years -operator-(const year& x, const year& y) NOEXCEPT -{ - return years{static_cast(x) - static_cast(y)}; +operator-(const year &x, const year &y) NOEXCEPT { + return years{static_cast(x) - static_cast(y)}; } CONSTCD11 inline year -operator+(const year& x, const years& y) NOEXCEPT -{ - return year{static_cast(x) + y.count()}; +operator+(const year &x, const years &y) NOEXCEPT { + return year{static_cast(x) + y.count()}; } CONSTCD11 inline year -operator+(const years& x, const year& y) NOEXCEPT -{ - return y + x; +operator+(const years &x, const year &y) NOEXCEPT { + return y + x; } CONSTCD11 inline year -operator-(const year& x, const years& y) NOEXCEPT -{ - return year{static_cast(x) - y.count()}; +operator-(const year &x, const years &y) NOEXCEPT { + return year{static_cast(x) - y.count()}; } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const year& y) +std::basic_ostream & +operator<<(std::basic_ostream &os, const year &y) { - detail::save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::internal); - os.width(4 + (y < year{0})); - os.imbue(std::locale::classic()); - os << static_cast(y); - if (!y.ok()) - os << " is not a valid year"; - return os; + detail::save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::internal); + os.width(4 + (y < year{0})); + os.imbue(std::locale::classic()); + os << static_cast(y); + if (!y.ok()) { + os << " is not a valid year"; + } + return os; } // weekday @@ -1719,154 +1687,148 @@ operator<<(std::basic_ostream& os, const year& y) CONSTCD14 inline unsigned char -weekday::weekday_from_days(int z) NOEXCEPT -{ - auto u = static_cast(z); - return static_cast(z >= -4 ? (u+4) % 7 : u % 7); +weekday::weekday_from_days(int z) NOEXCEPT { + auto u = static_cast(z); + return static_cast(z >= -4 ? (u + 4) % 7 : u % 7); } CONSTCD11 inline weekday::weekday(unsigned wd) NOEXCEPT - : wd_(static_cast(wd != 7 ? wd : 0)) - {} +: +wd_(static_cast(wd != 7 ? wd : 0)) +{} CONSTCD14 inline -weekday::weekday(const sys_days& dp) NOEXCEPT - : wd_(weekday_from_days(dp.time_since_epoch().count())) - {} +weekday::weekday(const sys_days &dp) NOEXCEPT +: +wd_(weekday_from_days(dp.time_since_epoch().count())) +{} CONSTCD14 inline -weekday::weekday(const local_days& dp) NOEXCEPT - : wd_(weekday_from_days(dp.time_since_epoch().count())) - {} +weekday::weekday(const local_days &dp) NOEXCEPT +: +wd_(weekday_from_days(dp.time_since_epoch().count())) +{} -CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;} +CONSTCD14 inline weekday &weekday::operator++() NOEXCEPT {*this += days{1}; return *this;} CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} -CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;} +CONSTCD14 inline weekday &weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;} CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} CONSTCD14 inline -weekday& -weekday::operator+=(const days& d) NOEXCEPT -{ - *this = *this + d; - return *this; +weekday & +weekday::operator+=(const days &d) NOEXCEPT { + *this = *this + d; + return *this; } CONSTCD14 inline -weekday& -weekday::operator-=(const days& d) NOEXCEPT -{ - *this = *this - d; - return *this; +weekday & +weekday::operator-=(const days &d) NOEXCEPT { + *this = *this - d; + return *this; } -CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;} +CONSTCD11 inline bool weekday::ok() const NOEXCEPT +{ + return wd_ <= 6; +} CONSTCD11 inline unsigned weekday::c_encoding() const NOEXCEPT { - return unsigned{wd_}; + return unsigned{wd_}; } CONSTCD11 inline unsigned weekday::iso_encoding() const NOEXCEPT { - return unsigned{((wd_ == 0u) ? 7u : wd_)}; + return unsigned{((wd_ == 0u) ? 7u : wd_)}; } CONSTCD11 inline bool -operator==(const weekday& x, const weekday& y) NOEXCEPT -{ - return x.wd_ == y.wd_; +operator==(const weekday &x, const weekday &y) NOEXCEPT { + return x.wd_ == y.wd_; } CONSTCD11 inline bool -operator!=(const weekday& x, const weekday& y) NOEXCEPT -{ - return !(x == y); +operator!=(const weekday &x, const weekday &y) NOEXCEPT { + return !(x == y); } CONSTCD14 inline days -operator-(const weekday& x, const weekday& y) NOEXCEPT -{ - auto const wdu = x.wd_ - y.wd_; - auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; - return days{wdu - wk * 7}; +operator-(const weekday &x, const weekday &y) NOEXCEPT { + auto const wdu = x.wd_ - y.wd_; + auto const wk = (wdu >= 0 ? wdu : wdu - 6) / 7; + return days{wdu - wk * 7}; } CONSTCD14 inline weekday -operator+(const weekday& x, const days& y) NOEXCEPT -{ - auto const wdu = static_cast(static_cast(x.wd_)) + y.count(); - auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; - return weekday{static_cast(wdu - wk * 7)}; +operator+(const weekday &x, const days &y) NOEXCEPT { + auto const wdu = static_cast(static_cast(x.wd_)) + y.count(); + auto const wk = (wdu >= 0 ? wdu : wdu - 6) / 7; + return weekday{static_cast(wdu - wk * 7)}; } CONSTCD14 inline weekday -operator+(const days& x, const weekday& y) NOEXCEPT -{ - return y + x; +operator+(const days &x, const weekday &y) NOEXCEPT { + return y + x; } CONSTCD14 inline weekday -operator-(const weekday& x, const days& y) NOEXCEPT -{ - return x + -y; +operator-(const weekday &x, const days &y) NOEXCEPT { + return x + -y; } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const weekday& wd) +std::basic_ostream & +operator<<(std::basic_ostream &os, const weekday &wd) { - if (wd.ok()) - { - CharT fmt[] = {'%', 'a', 0}; - os << format(fmt, wd); - } - else - os << static_cast(wd.wd_) << " is not a valid weekday"; - return os; + if (wd.ok()) { + CharT fmt[] = {'%', 'a', 0}; + os << format(fmt, wd); + } + else { + os << static_cast(wd.wd_) << " is not a valid weekday"; + } + return os; } #if !defined(_MSC_VER) || (_MSC_VER >= 1900) -inline namespace literals -{ +inline namespace literals { CONSTCD11 inline date::day -operator "" _d(unsigned long long d) NOEXCEPT -{ - return date::day{static_cast(d)}; +operator "" _d(unsigned long long d) NOEXCEPT { + return date::day{static_cast(d)}; } CONSTCD11 inline date::year -operator "" _y(unsigned long long y) NOEXCEPT -{ - return date::year(static_cast(y)); +operator "" _y(unsigned long long y) NOEXCEPT { + return date::year(static_cast(y)); } #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) @@ -1925,17 +1887,20 @@ inline weekday weekday_indexed::weekday() const NOEXCEPT { - return date::weekday{static_cast(wd_)}; + return date::weekday{static_cast(wd_)}; } -CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;} +CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT +{ + return index_; +} CONSTCD11 inline bool weekday_indexed::ok() const NOEXCEPT { - return weekday().ok() && 1 <= index_ && index_ <= 5; + return weekday().ok() && 1 <= index_ && index_ <= 5; } #ifdef __GNUC__ @@ -1945,10 +1910,11 @@ weekday_indexed::ok() const NOEXCEPT CONSTCD11 inline -weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT - : wd_(static_cast(static_cast(wd.wd_))) - , index_(static_cast(index)) - {} +weekday_indexed::weekday_indexed(const date::weekday &wd, unsigned index) NOEXCEPT +: +wd_(static_cast(static_cast(wd.wd_))) +, index_(static_cast(index)) +{} #ifdef __GNUC__ # pragma GCC diagnostic pop @@ -1956,14 +1922,15 @@ weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCE template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const weekday_indexed& wdi) +std::basic_ostream & +operator<<(std::basic_ostream &os, const weekday_indexed &wdi) { - os << wdi.weekday() << '[' << wdi.index(); - if (!(1 <= wdi.index() && wdi.index() <= 5)) - os << " is not a valid index"; - os << ']'; - return os; + os << wdi.weekday() << '[' << wdi.index(); + if (!(1 <= wdi.index() && wdi.index() <= 5)) { + os << " is not a valid index"; + } + os << ']'; + return os; } CONSTCD11 @@ -1971,53 +1938,56 @@ inline weekday_indexed weekday::operator[](unsigned index) const NOEXCEPT { - return {*this, index}; + return {*this, index}; } CONSTCD11 inline bool -operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT -{ - return x.weekday() == y.weekday() && x.index() == y.index(); +operator==(const weekday_indexed &x, const weekday_indexed &y) NOEXCEPT { + return x.weekday() == y.weekday() && x.index() == y.index(); } CONSTCD11 inline bool -operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT -{ - return !(x == y); +operator!=(const weekday_indexed &x, const weekday_indexed &y) NOEXCEPT { + return !(x == y); } // weekday_last -CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;} -CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();} -CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {} +CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT +{ + return wd_; +} +CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT +{ + return wd_.ok(); +} +CONSTCD11 inline weekday_last::weekday_last(const date::weekday &wd) NOEXCEPT : +wd_(wd) {} CONSTCD11 inline bool -operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT -{ - return x.weekday() == y.weekday(); +operator==(const weekday_last &x, const weekday_last &y) NOEXCEPT { + return x.weekday() == y.weekday(); } CONSTCD11 inline bool -operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT -{ - return !(x == y); +operator!=(const weekday_last &x, const weekday_last &y) NOEXCEPT { + return !(x == y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const weekday_last& wdl) +std::basic_ostream & +operator<<(std::basic_ostream &os, const weekday_last &wdl) { - return os << wdl.weekday() << "[last]"; + return os << wdl.weekday() << "[last]"; } CONSTCD11 @@ -2025,346 +1995,344 @@ inline weekday_last weekday::operator[](last_spec) const NOEXCEPT { - return weekday_last{*this}; + return weekday_last{*this}; } // year_month CONSTCD11 inline -year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT - : y_(y) - , m_(m) - {} +year_month::year_month(const date::year &y, const date::month &m) NOEXCEPT +: +y_(y) +, m_(m) +{} -CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;} -CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;} -CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();} - -template -CONSTCD14 -inline -year_month& -year_month::operator+=(const months& dm) NOEXCEPT +CONSTCD11 inline year year_month::year() const NOEXCEPT { - *this = *this + dm; - return *this; + return y_; +} +CONSTCD11 inline month year_month::month() const NOEXCEPT +{ + return m_; +} +CONSTCD11 inline bool year_month::ok() const NOEXCEPT +{ + return y_.ok() && m_.ok(); } template CONSTCD14 inline -year_month& -year_month::operator-=(const months& dm) NOEXCEPT -{ - *this = *this - dm; - return *this; +year_month & +year_month::operator+=(const months &dm) NOEXCEPT { + *this = *this + dm; + return *this; +} + +template +CONSTCD14 +inline +year_month & +year_month::operator-=(const months &dm) NOEXCEPT { + *this = *this - dm; + return *this; } CONSTCD14 inline -year_month& -year_month::operator+=(const years& dy) NOEXCEPT -{ - *this = *this + dy; - return *this; +year_month & +year_month::operator+=(const years &dy) NOEXCEPT { + *this = *this + dy; + return *this; } CONSTCD14 inline -year_month& -year_month::operator-=(const years& dy) NOEXCEPT -{ - *this = *this - dy; - return *this; +year_month & +year_month::operator-=(const years &dy) NOEXCEPT { + *this = *this - dy; + return *this; } CONSTCD11 inline bool -operator==(const year_month& x, const year_month& y) NOEXCEPT -{ - return x.year() == y.year() && x.month() == y.month(); +operator==(const year_month &x, const year_month &y) NOEXCEPT { + return x.year() == y.year() && x.month() == y.month(); } CONSTCD11 inline bool -operator!=(const year_month& x, const year_month& y) NOEXCEPT -{ - return !(x == y); +operator!=(const year_month &x, const year_month &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator<(const year_month& x, const year_month& y) NOEXCEPT -{ - return x.year() < y.year() ? true - : (x.year() > y.year() ? false - : (x.month() < y.month())); +operator<(const year_month &x, const year_month &y) NOEXCEPT { + return x.year() < y.year() ? true + : (x.year() > y.year() ? false + : (x.month() < y.month())); } CONSTCD11 inline bool -operator>(const year_month& x, const year_month& y) NOEXCEPT -{ - return y < x; +operator>(const year_month &x, const year_month &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator<=(const year_month& x, const year_month& y) NOEXCEPT -{ - return !(y < x); +operator<=(const year_month &x, const year_month &y) NOEXCEPT { + return !(y < x); } CONSTCD11 inline bool -operator>=(const year_month& x, const year_month& y) NOEXCEPT -{ - return !(x < y); +operator>=(const year_month &x, const year_month &y) NOEXCEPT { + return !(x < y); } template CONSTCD14 inline year_month -operator+(const year_month& ym, const months& dm) NOEXCEPT -{ - auto dmi = static_cast(static_cast(ym.month())) - 1 + dm.count(); - auto dy = (dmi >= 0 ? dmi : dmi-11) / 12; - dmi = dmi - dy * 12 + 1; - return (ym.year() + years(dy)) / month(static_cast(dmi)); +operator+(const year_month &ym, const months &dm) NOEXCEPT { + auto dmi = static_cast(static_cast(ym.month())) - 1 + dm.count(); + auto dy = (dmi >= 0 ? dmi : dmi - 11) / 12; + dmi = dmi - dy * 12 + 1; + return (ym.year() + years(dy)) / month(static_cast(dmi)); } template CONSTCD14 inline year_month -operator+(const months& dm, const year_month& ym) NOEXCEPT -{ - return ym + dm; +operator+(const months &dm, const year_month &ym) NOEXCEPT { + return ym + dm; } template CONSTCD14 inline year_month -operator-(const year_month& ym, const months& dm) NOEXCEPT -{ - return ym + -dm; +operator-(const year_month &ym, const months &dm) NOEXCEPT { + return ym + -dm; } CONSTCD11 inline months -operator-(const year_month& x, const year_month& y) NOEXCEPT -{ - return (x.year() - y.year()) + - months(static_cast(x.month()) - static_cast(y.month())); +operator-(const year_month &x, const year_month &y) NOEXCEPT { + return (x.year() - y.year()) + + months(static_cast(x.month()) - static_cast(y.month())); } CONSTCD11 inline year_month -operator+(const year_month& ym, const years& dy) NOEXCEPT -{ - return (ym.year() + dy) / ym.month(); +operator+(const year_month &ym, const years &dy) NOEXCEPT { + return (ym.year() + dy) / ym.month(); } CONSTCD11 inline year_month -operator+(const years& dy, const year_month& ym) NOEXCEPT -{ - return ym + dy; +operator+(const years &dy, const year_month &ym) NOEXCEPT { + return ym + dy; } CONSTCD11 inline year_month -operator-(const year_month& ym, const years& dy) NOEXCEPT -{ - return ym + -dy; +operator-(const year_month &ym, const years &dy) NOEXCEPT { + return ym + -dy; } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month& ym) +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month &ym) { - return os << ym.year() << '/' << ym.month(); + return os << ym.year() << '/' << ym.month(); } // month_day CONSTCD11 inline -month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT - : m_(m) - , d_(d) - {} +month_day::month_day(const date::month &m, const date::day &d) NOEXCEPT +: +m_(m) +, d_(d) +{} -CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;} -CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;} +CONSTCD11 inline date::month month_day::month() const NOEXCEPT +{ + return m_; +} +CONSTCD11 inline date::day month_day::day() const NOEXCEPT +{ + return d_; +} CONSTCD14 inline bool month_day::ok() const NOEXCEPT { - CONSTDATA date::day d[] = - { - date::day(31), date::day(29), date::day(31), - date::day(30), date::day(31), date::day(30), - date::day(31), date::day(31), date::day(30), - date::day(31), date::day(30), date::day(31) - }; - return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast(m_)-1]; + CONSTDATA date::day d[] = { + date::day(31), date::day(29), date::day(31), + date::day(30), date::day(31), date::day(30), + date::day(31), date::day(31), date::day(30), + date::day(31), date::day(30), date::day(31) + }; + return m_.ok() && date::day{1} <= d_ &&d_ <= d[static_cast(m_) - 1]; } CONSTCD11 inline bool -operator==(const month_day& x, const month_day& y) NOEXCEPT -{ - return x.month() == y.month() && x.day() == y.day(); +operator==(const month_day &x, const month_day &y) NOEXCEPT { + return x.month() == y.month() && x.day() == y.day(); } CONSTCD11 inline bool -operator!=(const month_day& x, const month_day& y) NOEXCEPT -{ - return !(x == y); +operator!=(const month_day &x, const month_day &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator<(const month_day& x, const month_day& y) NOEXCEPT -{ - return x.month() < y.month() ? true - : (x.month() > y.month() ? false - : (x.day() < y.day())); +operator<(const month_day &x, const month_day &y) NOEXCEPT { + return x.month() < y.month() ? true + : (x.month() > y.month() ? false + : (x.day() < y.day())); } CONSTCD11 inline bool -operator>(const month_day& x, const month_day& y) NOEXCEPT -{ - return y < x; +operator>(const month_day &x, const month_day &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator<=(const month_day& x, const month_day& y) NOEXCEPT -{ - return !(y < x); +operator<=(const month_day &x, const month_day &y) NOEXCEPT { + return !(y < x); } CONSTCD11 inline bool -operator>=(const month_day& x, const month_day& y) NOEXCEPT -{ - return !(x < y); +operator>=(const month_day &x, const month_day &y) NOEXCEPT { + return !(x < y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_day& md) +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_day &md) { - return os << md.month() << '/' << md.day(); + return os << md.month() << '/' << md.day(); } // month_day_last -CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;} -CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();} -CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {} +CONSTCD11 inline month month_day_last::month() const NOEXCEPT +{ + return m_; +} +CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT +{ + return m_.ok(); +} +CONSTCD11 inline month_day_last::month_day_last(const date::month &m) NOEXCEPT : +m_(m) {} CONSTCD11 inline bool -operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT -{ - return x.month() == y.month(); +operator==(const month_day_last &x, const month_day_last &y) NOEXCEPT { + return x.month() == y.month(); } CONSTCD11 inline bool -operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT -{ - return !(x == y); +operator!=(const month_day_last &x, const month_day_last &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT -{ - return x.month() < y.month(); +operator<(const month_day_last &x, const month_day_last &y) NOEXCEPT { + return x.month() < y.month(); } CONSTCD11 inline bool -operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT -{ - return y < x; +operator>(const month_day_last &x, const month_day_last &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT -{ - return !(y < x); +operator<=(const month_day_last &x, const month_day_last &y) NOEXCEPT { + return !(y < x); } CONSTCD11 inline bool -operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT -{ - return !(x < y); +operator>=(const month_day_last &x, const month_day_last &y) NOEXCEPT { + return !(x < y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_day_last& mdl) +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_day_last &mdl) { - return os << mdl.month() << "/last"; + return os << mdl.month() << "/last"; } // month_weekday CONSTCD11 inline -month_weekday::month_weekday(const date::month& m, - const date::weekday_indexed& wdi) NOEXCEPT - : m_(m) - , wdi_(wdi) - {} +month_weekday::month_weekday(const date::month &m, + const date::weekday_indexed &wdi) NOEXCEPT +: +m_(m) +, wdi_(wdi) +{} -CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;} +CONSTCD11 inline month month_weekday::month() const NOEXCEPT +{ + return m_; +} CONSTCD11 inline weekday_indexed month_weekday::weekday_indexed() const NOEXCEPT { - return wdi_; + return wdi_; } CONSTCD11 @@ -2372,51 +2340,53 @@ inline bool month_weekday::ok() const NOEXCEPT { - return m_.ok() && wdi_.ok(); + return m_.ok() && wdi_.ok(); } CONSTCD11 inline bool -operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT -{ - return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); +operator==(const month_weekday &x, const month_weekday &y) NOEXCEPT { + return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); } CONSTCD11 inline bool -operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT -{ - return !(x == y); +operator!=(const month_weekday &x, const month_weekday &y) NOEXCEPT { + return !(x == y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_weekday& mwd) +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_weekday &mwd) { - return os << mwd.month() << '/' << mwd.weekday_indexed(); + return os << mwd.month() << '/' << mwd.weekday_indexed(); } // month_weekday_last CONSTCD11 inline -month_weekday_last::month_weekday_last(const date::month& m, - const date::weekday_last& wdl) NOEXCEPT - : m_(m) - , wdl_(wdl) - {} +month_weekday_last::month_weekday_last(const date::month &m, + const date::weekday_last &wdl) NOEXCEPT +: +m_(m) +, wdl_(wdl) +{} -CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;} +CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT +{ + return m_; +} CONSTCD11 inline weekday_last month_weekday_last::weekday_last() const NOEXCEPT { - return wdl_; + return wdl_; } CONSTCD11 @@ -2424,90 +2394,91 @@ inline bool month_weekday_last::ok() const NOEXCEPT { - return m_.ok() && wdl_.ok(); + return m_.ok() && wdl_.ok(); } CONSTCD11 inline bool -operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT -{ - return x.month() == y.month() && x.weekday_last() == y.weekday_last(); +operator==(const month_weekday_last &x, const month_weekday_last &y) NOEXCEPT { + return x.month() == y.month() && x.weekday_last() == y.weekday_last(); } CONSTCD11 inline bool -operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT -{ - return !(x == y); +operator!=(const month_weekday_last &x, const month_weekday_last &y) NOEXCEPT { + return !(x == y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const month_weekday_last& mwdl) +std::basic_ostream & +operator<<(std::basic_ostream &os, const month_weekday_last &mwdl) { - return os << mwdl.month() << '/' << mwdl.weekday_last(); + return os << mwdl.month() << '/' << mwdl.weekday_last(); } // year_month_day_last CONSTCD11 inline -year_month_day_last::year_month_day_last(const date::year& y, - const date::month_day_last& mdl) NOEXCEPT - : y_(y) - , mdl_(mdl) - {} +year_month_day_last::year_month_day_last(const date::year &y, + const date::month_day_last &mdl) NOEXCEPT +: +y_(y) +, mdl_(mdl) +{} template CONSTCD14 inline -year_month_day_last& -year_month_day_last::operator+=(const months& m) NOEXCEPT -{ - *this = *this + m; - return *this; +year_month_day_last & +year_month_day_last::operator+=(const months &m) NOEXCEPT { + *this = *this + m; + return *this; } template CONSTCD14 inline -year_month_day_last& -year_month_day_last::operator-=(const months& m) NOEXCEPT -{ - *this = *this - m; - return *this; +year_month_day_last & +year_month_day_last::operator-=(const months &m) NOEXCEPT { + *this = *this - m; + return *this; } CONSTCD14 inline -year_month_day_last& -year_month_day_last::operator+=(const years& y) NOEXCEPT -{ - *this = *this + y; - return *this; +year_month_day_last & +year_month_day_last::operator+=(const years &y) NOEXCEPT { + *this = *this + y; + return *this; } CONSTCD14 inline -year_month_day_last& -year_month_day_last::operator-=(const years& y) NOEXCEPT -{ - *this = *this - y; - return *this; +year_month_day_last & +year_month_day_last::operator-=(const years &y) NOEXCEPT { + *this = *this - y; + return *this; } -CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;} -CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();} +CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT +{ + return y_; +} +CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT +{ + return mdl_.month(); +} CONSTCD11 inline month_day_last year_month_day_last::month_day_last() const NOEXCEPT { - return mdl_; + return mdl_; } CONSTCD14 @@ -2515,29 +2486,28 @@ inline day year_month_day_last::day() const NOEXCEPT { - CONSTDATA date::day d[] = - { - date::day(31), date::day(28), date::day(31), - date::day(30), date::day(31), date::day(30), - date::day(31), date::day(31), date::day(30), - date::day(31), date::day(30), date::day(31) - }; - return (month() != February || !y_.is_leap()) && mdl_.ok() ? - d[static_cast(month()) - 1] : date::day{29}; + CONSTDATA date::day d[] = { + date::day(31), date::day(28), date::day(31), + date::day(30), date::day(31), date::day(30), + date::day(31), date::day(31), date::day(30), + date::day(31), date::day(30), date::day(31) + }; + return (month() != February || !y_.is_leap()) && mdl_.ok() ? + d[static_cast(month()) - 1] : date::day{29}; } CONSTCD14 inline year_month_day_last::operator sys_days() const NOEXCEPT { - return sys_days(year()/month()/day()); + return sys_days(year() / month() / day()); } CONSTCD14 inline year_month_day_last::operator local_days() const NOEXCEPT { - return local_days(year()/month()/day()); + return local_days(year() / month() / day()); } CONSTCD11 @@ -2545,189 +2515,186 @@ inline bool year_month_day_last::ok() const NOEXCEPT { - return y_.ok() && mdl_.ok(); + return y_.ok() && mdl_.ok(); } CONSTCD11 inline bool -operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT -{ - return x.year() == y.year() && x.month_day_last() == y.month_day_last(); +operator==(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT { + return x.year() == y.year() && x.month_day_last() == y.month_day_last(); } CONSTCD11 inline bool -operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT -{ - return !(x == y); +operator!=(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT -{ - return x.year() < y.year() ? true - : (x.year() > y.year() ? false - : (x.month_day_last() < y.month_day_last())); +operator<(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT { + return x.year() < y.year() ? true + : (x.year() > y.year() ? false + : (x.month_day_last() < y.month_day_last())); } CONSTCD11 inline bool -operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT -{ - return y < x; +operator>(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT -{ - return !(y < x); +operator<=(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT { + return !(y < x); } CONSTCD11 inline bool -operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT -{ - return !(x < y); +operator>=(const year_month_day_last &x, const year_month_day_last &y) NOEXCEPT { + return !(x < y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_day_last& ymdl) +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_day_last &ymdl) { - return os << ymdl.year() << '/' << ymdl.month_day_last(); + return os << ymdl.year() << '/' << ymdl.month_day_last(); } template CONSTCD14 inline year_month_day_last -operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT -{ - return (ymdl.year() / ymdl.month() + dm) / last; +operator+(const year_month_day_last &ymdl, const months &dm) NOEXCEPT { + return (ymdl.year() / ymdl.month() + dm) / last; } template CONSTCD14 inline year_month_day_last -operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT -{ - return ymdl + dm; +operator+(const months &dm, const year_month_day_last &ymdl) NOEXCEPT { + return ymdl + dm; } template CONSTCD14 inline year_month_day_last -operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT -{ - return ymdl + (-dm); +operator-(const year_month_day_last &ymdl, const months &dm) NOEXCEPT { + return ymdl + (-dm); } CONSTCD11 inline year_month_day_last -operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT -{ - return {ymdl.year()+dy, ymdl.month_day_last()}; +operator+(const year_month_day_last &ymdl, const years &dy) NOEXCEPT { + return {ymdl.year() + dy, ymdl.month_day_last()}; } CONSTCD11 inline year_month_day_last -operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT -{ - return ymdl + dy; +operator+(const years &dy, const year_month_day_last &ymdl) NOEXCEPT { + return ymdl + dy; } CONSTCD11 inline year_month_day_last -operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT -{ - return ymdl + (-dy); +operator-(const year_month_day_last &ymdl, const years &dy) NOEXCEPT { + return ymdl + (-dy); } // year_month_day CONSTCD11 inline -year_month_day::year_month_day(const date::year& y, const date::month& m, - const date::day& d) NOEXCEPT - : y_(y) - , m_(m) - , d_(d) - {} +year_month_day::year_month_day(const date::year &y, const date::month &m, + const date::day &d) NOEXCEPT +: +y_(y) +, m_(m) +, d_(d) +{} CONSTCD14 inline -year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT - : y_(ymdl.year()) - , m_(ymdl.month()) - , d_(ymdl.day()) - {} +year_month_day::year_month_day(const year_month_day_last &ymdl) NOEXCEPT +: +y_(ymdl.year()) +, m_(ymdl.month()) +, d_(ymdl.day()) +{} CONSTCD14 inline year_month_day::year_month_day(sys_days dp) NOEXCEPT - : year_month_day(from_days(dp.time_since_epoch())) - {} +: +year_month_day(from_days(dp.time_since_epoch())) +{} CONSTCD14 inline year_month_day::year_month_day(local_days dp) NOEXCEPT - : year_month_day(from_days(dp.time_since_epoch())) - {} +: +year_month_day(from_days(dp.time_since_epoch())) +{} -CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;} -CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;} -CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;} - -template -CONSTCD14 -inline -year_month_day& -year_month_day::operator+=(const months& m) NOEXCEPT +CONSTCD11 inline year year_month_day::year() const NOEXCEPT { - *this = *this + m; - return *this; + return y_; +} +CONSTCD11 inline month year_month_day::month() const NOEXCEPT +{ + return m_; +} +CONSTCD11 inline day year_month_day::day() const NOEXCEPT +{ + return d_; } template CONSTCD14 inline -year_month_day& -year_month_day::operator-=(const months& m) NOEXCEPT -{ - *this = *this - m; - return *this; +year_month_day & +year_month_day::operator+=(const months &m) NOEXCEPT { + *this = *this + m; + return *this; +} + +template +CONSTCD14 +inline +year_month_day & +year_month_day::operator-=(const months &m) NOEXCEPT { + *this = *this - m; + return *this; } CONSTCD14 inline -year_month_day& -year_month_day::operator+=(const years& y) NOEXCEPT -{ - *this = *this + y; - return *this; +year_month_day & +year_month_day::operator+=(const years &y) NOEXCEPT { + *this = *this + y; + return *this; } CONSTCD14 inline -year_month_day& -year_month_day::operator-=(const years& y) NOEXCEPT -{ - *this = *this - y; - return *this; +year_month_day & +year_month_day::operator-=(const years &y) NOEXCEPT { + *this = *this - y; + return *this; } CONSTCD14 @@ -2735,32 +2702,32 @@ inline days year_month_day::to_days() const NOEXCEPT { - static_assert(std::numeric_limits::digits >= 18, - "This algorithm has not been ported to a 16 bit unsigned integer"); - static_assert(std::numeric_limits::digits >= 20, - "This algorithm has not been ported to a 16 bit signed integer"); - auto const y = static_cast(y_) - (m_ <= February); - auto const m = static_cast(m_); - auto const d = static_cast(d_); - auto const era = (y >= 0 ? y : y-399) / 400; - auto const yoe = static_cast(y - era * 400); // [0, 399] - auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365] - auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096] - return days{era * 146097 + static_cast(doe) - 719468}; + static_assert(std::numeric_limits::digits >= 18, + "This algorithm has not been ported to a 16 bit unsigned integer"); + static_assert(std::numeric_limits::digits >= 20, + "This algorithm has not been ported to a 16 bit signed integer"); + auto const y = static_cast(y_) - (m_ <= February); + auto const m = static_cast(m_); + auto const d = static_cast(d_); + auto const era = (y >= 0 ? y : y - 399) / 400; + auto const yoe = static_cast(y - era * 400); // [0, 399] + auto const doy = (153 * (m > 2 ? m - 3 : m + 9) + 2) / 5 + d - 1; // [0, 365] + auto const doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096] + return days{era * 146097 + static_cast(doe) - 719468}; } CONSTCD14 inline year_month_day::operator sys_days() const NOEXCEPT { - return sys_days{to_days()}; + return sys_days{to_days()}; } CONSTCD14 inline year_month_day::operator local_days() const NOEXCEPT { - return local_days{to_days()}; + return local_days{to_days()}; } CONSTCD14 @@ -2768,223 +2735,217 @@ inline bool year_month_day::ok() const NOEXCEPT { - if (!(y_.ok() && m_.ok())) - return false; - return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day(); + if (!(y_.ok() && m_.ok())) { + return false; + } + return date::day{1} <= d_ &&d_ <= (y_ / m_ / last).day(); } CONSTCD11 inline bool -operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT -{ - return x.year() == y.year() && x.month() == y.month() && x.day() == y.day(); +operator==(const year_month_day &x, const year_month_day &y) NOEXCEPT { + return x.year() == y.year() && x.month() == y.month() && x.day() == y.day(); } CONSTCD11 inline bool -operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT -{ - return !(x == y); +operator!=(const year_month_day &x, const year_month_day &y) NOEXCEPT { + return !(x == y); } CONSTCD11 inline bool -operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT -{ - return x.year() < y.year() ? true - : (x.year() > y.year() ? false - : (x.month() < y.month() ? true +operator<(const year_month_day &x, const year_month_day &y) NOEXCEPT { + return x.year() < y.year() ? true + : (x.year() > y.year() ? false + : (x.month() < y.month() ? true : (x.month() > y.month() ? false - : (x.day() < y.day())))); + : (x.day() < y.day())))); } CONSTCD11 inline bool -operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT -{ - return y < x; +operator>(const year_month_day &x, const year_month_day &y) NOEXCEPT { + return y < x; } CONSTCD11 inline bool -operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT -{ - return !(y < x); +operator<=(const year_month_day &x, const year_month_day &y) NOEXCEPT { + return !(y < x); } CONSTCD11 inline bool -operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT -{ - return !(x < y); +operator>=(const year_month_day &x, const year_month_day &y) NOEXCEPT { + return !(x < y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_day& ymd) +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_day &ymd) { - detail::save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os << ymd.year() << '-'; - os.width(2); - os << static_cast(ymd.month()) << '-'; - os << ymd.day(); - if (!ymd.ok()) - os << " is not a valid date"; - return os; + detail::save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os << ymd.year() << '-'; + os.width(2); + os << static_cast(ymd.month()) << '-'; + os << ymd.day(); + if (!ymd.ok()) { + os << " is not a valid date"; + } + return os; } CONSTCD14 inline year_month_day -year_month_day::from_days(days dp) NOEXCEPT -{ - static_assert(std::numeric_limits::digits >= 18, - "This algorithm has not been ported to a 16 bit unsigned integer"); - static_assert(std::numeric_limits::digits >= 20, - "This algorithm has not been ported to a 16 bit signed integer"); - auto const z = dp.count() + 719468; - auto const era = (z >= 0 ? z : z - 146096) / 146097; - auto const doe = static_cast(z - era * 146097); // [0, 146096] - auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] - auto const y = static_cast(yoe) + era * 400; - auto const doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] - auto const mp = (5*doy + 2)/153; // [0, 11] - auto const d = doy - (153*mp+2)/5 + 1; // [1, 31] - auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12] - return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)}; +year_month_day::from_days(days dp) NOEXCEPT { + static_assert(std::numeric_limits::digits >= 18, + "This algorithm has not been ported to a 16 bit unsigned integer"); + static_assert(std::numeric_limits::digits >= 20, + "This algorithm has not been ported to a 16 bit signed integer"); + auto const z = dp.count() + 719468; + auto const era = (z >= 0 ? z : z - 146096) / 146097; + auto const doe = static_cast(z - era * 146097); // [0, 146096] + auto const yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] + auto const y = static_cast(yoe) + era * 400; + auto const doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + auto const mp = (5 * doy + 2) / 153; // [0, 11] + auto const d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + auto const m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] + return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)}; } template CONSTCD14 inline year_month_day -operator+(const year_month_day& ymd, const months& dm) NOEXCEPT -{ - return (ymd.year() / ymd.month() + dm) / ymd.day(); +operator+(const year_month_day &ymd, const months &dm) NOEXCEPT { + return (ymd.year() / ymd.month() + dm) / ymd.day(); } template CONSTCD14 inline year_month_day -operator+(const months& dm, const year_month_day& ymd) NOEXCEPT -{ - return ymd + dm; +operator+(const months &dm, const year_month_day &ymd) NOEXCEPT { + return ymd + dm; } template CONSTCD14 inline year_month_day -operator-(const year_month_day& ymd, const months& dm) NOEXCEPT -{ - return ymd + (-dm); +operator-(const year_month_day &ymd, const months &dm) NOEXCEPT { + return ymd + (-dm); } CONSTCD11 inline year_month_day -operator+(const year_month_day& ymd, const years& dy) NOEXCEPT -{ - return (ymd.year() + dy) / ymd.month() / ymd.day(); +operator+(const year_month_day &ymd, const years &dy) NOEXCEPT { + return (ymd.year() + dy) / ymd.month() / ymd.day(); } CONSTCD11 inline year_month_day -operator+(const years& dy, const year_month_day& ymd) NOEXCEPT -{ - return ymd + dy; +operator+(const years &dy, const year_month_day &ymd) NOEXCEPT { + return ymd + dy; } CONSTCD11 inline year_month_day -operator-(const year_month_day& ymd, const years& dy) NOEXCEPT -{ - return ymd + (-dy); +operator-(const year_month_day &ymd, const years &dy) NOEXCEPT { + return ymd + (-dy); } // year_month_weekday CONSTCD11 inline -year_month_weekday::year_month_weekday(const date::year& y, const date::month& m, - const date::weekday_indexed& wdi) - NOEXCEPT - : y_(y) - , m_(m) - , wdi_(wdi) - {} +year_month_weekday::year_month_weekday(const date::year &y, const date::month &m, + const date::weekday_indexed &wdi) +NOEXCEPT +: +y_(y) +, m_(m) +, wdi_(wdi) +{} CONSTCD14 inline -year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT - : year_month_weekday(from_days(dp.time_since_epoch())) - {} +year_month_weekday::year_month_weekday(const sys_days &dp) NOEXCEPT +: +year_month_weekday(from_days(dp.time_since_epoch())) +{} CONSTCD14 inline -year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT - : year_month_weekday(from_days(dp.time_since_epoch())) - {} +year_month_weekday::year_month_weekday(const local_days &dp) NOEXCEPT +: +year_month_weekday(from_days(dp.time_since_epoch())) +{} template CONSTCD14 inline -year_month_weekday& -year_month_weekday::operator+=(const months& m) NOEXCEPT -{ - *this = *this + m; - return *this; +year_month_weekday & +year_month_weekday::operator+=(const months &m) NOEXCEPT { + *this = *this + m; + return *this; } template CONSTCD14 inline -year_month_weekday& -year_month_weekday::operator-=(const months& m) NOEXCEPT -{ - *this = *this - m; - return *this; +year_month_weekday & +year_month_weekday::operator-=(const months &m) NOEXCEPT { + *this = *this - m; + return *this; } CONSTCD14 inline -year_month_weekday& -year_month_weekday::operator+=(const years& y) NOEXCEPT -{ - *this = *this + y; - return *this; +year_month_weekday & +year_month_weekday::operator+=(const years &y) NOEXCEPT { + *this = *this + y; + return *this; } CONSTCD14 inline -year_month_weekday& -year_month_weekday::operator-=(const years& y) NOEXCEPT -{ - *this = *this - y; - return *this; +year_month_weekday & +year_month_weekday::operator-=(const years &y) NOEXCEPT { + *this = *this - y; + return *this; } -CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;} -CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;} +CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT +{ + return y_; +} +CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT +{ + return m_; +} CONSTCD11 inline weekday year_month_weekday::weekday() const NOEXCEPT { - return wdi_.weekday(); + return wdi_.weekday(); } CONSTCD11 @@ -2992,7 +2953,7 @@ inline unsigned year_month_weekday::index() const NOEXCEPT { - return wdi_.index(); + return wdi_.index(); } CONSTCD11 @@ -3000,21 +2961,21 @@ inline weekday_indexed year_month_weekday::weekday_indexed() const NOEXCEPT { - return wdi_; + return wdi_; } CONSTCD14 inline year_month_weekday::operator sys_days() const NOEXCEPT { - return sys_days{to_days()}; + return sys_days{to_days()}; } CONSTCD14 inline year_month_weekday::operator local_days() const NOEXCEPT { - return local_days{to_days()}; + return local_days{to_days()}; } CONSTCD14 @@ -3022,24 +2983,25 @@ inline bool year_month_weekday::ok() const NOEXCEPT { - if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1) - return false; - if (wdi_.index() <= 4) - return true; - auto d2 = wdi_.weekday() - date::weekday(static_cast(y_/m_/1)) + - days((wdi_.index()-1)*7 + 1); - return static_cast(d2.count()) <= static_cast((y_/m_/last).day()); + if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1) { + return false; + } + if (wdi_.index() <= 4) { + return true; + } + auto d2 = wdi_.weekday() - date::weekday(static_cast(y_ / m_ / 1)) + + days((wdi_.index() - 1) * 7 + 1); + return static_cast(d2.count()) <= static_cast((y_ / m_ / last).day()); } CONSTCD14 inline year_month_weekday -year_month_weekday::from_days(days d) NOEXCEPT -{ - sys_days dp{d}; - auto const wd = date::weekday(dp); - auto const ymd = year_month_day(dp); - return {ymd.year(), ymd.month(), wd[(static_cast(ymd.day())-1)/7+1]}; +year_month_weekday::from_days(days d) NOEXCEPT { + sys_days dp{d}; + auto const wd = date::weekday(dp); + auto const ymd = year_month_day(dp); + return {ymd.year(), ymd.month(), wd[(static_cast(ymd.day()) - 1) / 7 + 1]}; } CONSTCD14 @@ -3047,147 +3009,142 @@ inline days year_month_weekday::to_days() const NOEXCEPT { - auto d = sys_days(y_/m_/1); - return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7}) - ).time_since_epoch(); + auto d = sys_days(y_ / m_ / 1); + return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index() - 1) * 7}) + ).time_since_epoch(); } CONSTCD11 inline bool -operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT -{ - return x.year() == y.year() && x.month() == y.month() && - x.weekday_indexed() == y.weekday_indexed(); +operator==(const year_month_weekday &x, const year_month_weekday &y) NOEXCEPT { + return x.year() == y.year() && x.month() == y.month() && + x.weekday_indexed() == y.weekday_indexed(); } CONSTCD11 inline bool -operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT -{ - return !(x == y); +operator!=(const year_month_weekday &x, const year_month_weekday &y) NOEXCEPT { + return !(x == y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi) +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_weekday &ymwdi) { - return os << ymwdi.year() << '/' << ymwdi.month() - << '/' << ymwdi.weekday_indexed(); + return os << ymwdi.year() << '/' << ymwdi.month() + << '/' << ymwdi.weekday_indexed(); } template CONSTCD14 inline year_month_weekday -operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT -{ - return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed(); +operator+(const year_month_weekday &ymwd, const months &dm) NOEXCEPT { + return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed(); } template CONSTCD14 inline year_month_weekday -operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT -{ - return ymwd + dm; +operator+(const months &dm, const year_month_weekday &ymwd) NOEXCEPT { + return ymwd + dm; } template CONSTCD14 inline year_month_weekday -operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT -{ - return ymwd + (-dm); +operator-(const year_month_weekday &ymwd, const months &dm) NOEXCEPT { + return ymwd + (-dm); } CONSTCD11 inline year_month_weekday -operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT -{ - return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}; +operator+(const year_month_weekday &ymwd, const years &dy) NOEXCEPT { + return {ymwd.year() + dy, ymwd.month(), ymwd.weekday_indexed()}; } CONSTCD11 inline year_month_weekday -operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT -{ - return ymwd + dy; +operator+(const years &dy, const year_month_weekday &ymwd) NOEXCEPT { + return ymwd + dy; } CONSTCD11 inline year_month_weekday -operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT -{ - return ymwd + (-dy); +operator-(const year_month_weekday &ymwd, const years &dy) NOEXCEPT { + return ymwd + (-dy); } // year_month_weekday_last CONSTCD11 inline -year_month_weekday_last::year_month_weekday_last(const date::year& y, - const date::month& m, - const date::weekday_last& wdl) NOEXCEPT - : y_(y) - , m_(m) - , wdl_(wdl) - {} +year_month_weekday_last::year_month_weekday_last(const date::year &y, + const date::month &m, + const date::weekday_last &wdl) NOEXCEPT +: +y_(y) +, m_(m) +, wdl_(wdl) +{} template CONSTCD14 inline -year_month_weekday_last& -year_month_weekday_last::operator+=(const months& m) NOEXCEPT -{ - *this = *this + m; - return *this; +year_month_weekday_last & +year_month_weekday_last::operator+=(const months &m) NOEXCEPT { + *this = *this + m; + return *this; } template CONSTCD14 inline -year_month_weekday_last& -year_month_weekday_last::operator-=(const months& m) NOEXCEPT -{ - *this = *this - m; - return *this; +year_month_weekday_last & +year_month_weekday_last::operator-=(const months &m) NOEXCEPT { + *this = *this - m; + return *this; } CONSTCD14 inline -year_month_weekday_last& -year_month_weekday_last::operator+=(const years& y) NOEXCEPT -{ - *this = *this + y; - return *this; +year_month_weekday_last & +year_month_weekday_last::operator+=(const years &y) NOEXCEPT { + *this = *this + y; + return *this; } CONSTCD14 inline -year_month_weekday_last& -year_month_weekday_last::operator-=(const years& y) NOEXCEPT -{ - *this = *this - y; - return *this; +year_month_weekday_last & +year_month_weekday_last::operator-=(const years &y) NOEXCEPT { + *this = *this - y; + return *this; } -CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;} -CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;} +CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT +{ + return y_; +} +CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT +{ + return m_; +} CONSTCD11 inline weekday year_month_weekday_last::weekday() const NOEXCEPT { - return wdl_.weekday(); + return wdl_.weekday(); } CONSTCD11 @@ -3195,21 +3152,21 @@ inline weekday_last year_month_weekday_last::weekday_last() const NOEXCEPT { - return wdl_; + return wdl_; } CONSTCD14 inline year_month_weekday_last::operator sys_days() const NOEXCEPT { - return sys_days{to_days()}; + return sys_days{to_days()}; } CONSTCD14 inline year_month_weekday_last::operator local_days() const NOEXCEPT { - return local_days{to_days()}; + return local_days{to_days()}; } CONSTCD11 @@ -3217,7 +3174,7 @@ inline bool year_month_weekday_last::ok() const NOEXCEPT { - return y_.ok() && m_.ok() && wdl_.ok(); + return y_.ok() && m_.ok() && wdl_.ok(); } CONSTCD14 @@ -3225,84 +3182,76 @@ inline days year_month_weekday_last::to_days() const NOEXCEPT { - auto const d = sys_days(y_/m_/last); - return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch(); + auto const d = sys_days(y_ / m_ / last); + return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch(); } CONSTCD11 inline bool -operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT -{ - return x.year() == y.year() && x.month() == y.month() && - x.weekday_last() == y.weekday_last(); +operator==(const year_month_weekday_last &x, const year_month_weekday_last &y) NOEXCEPT { + return x.year() == y.year() && x.month() == y.month() && + x.weekday_last() == y.weekday_last(); } CONSTCD11 inline bool -operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT -{ - return !(x == y); +operator!=(const year_month_weekday_last &x, const year_month_weekday_last &y) NOEXCEPT { + return !(x == y); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl) +std::basic_ostream & +operator<<(std::basic_ostream &os, const year_month_weekday_last &ymwdl) { - return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last(); + return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last(); } template CONSTCD14 inline year_month_weekday_last -operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT -{ - return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last(); +operator+(const year_month_weekday_last &ymwdl, const months &dm) NOEXCEPT { + return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last(); } template CONSTCD14 inline year_month_weekday_last -operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT -{ - return ymwdl + dm; +operator+(const months &dm, const year_month_weekday_last &ymwdl) NOEXCEPT { + return ymwdl + dm; } template CONSTCD14 inline year_month_weekday_last -operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT -{ - return ymwdl + (-dm); +operator-(const year_month_weekday_last &ymwdl, const months &dm) NOEXCEPT { + return ymwdl + (-dm); } CONSTCD11 inline year_month_weekday_last -operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT -{ - return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}; +operator+(const year_month_weekday_last &ymwdl, const years &dy) NOEXCEPT { + return {ymwdl.year() + dy, ymwdl.month(), ymwdl.weekday_last()}; } CONSTCD11 inline year_month_weekday_last -operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT -{ - return ymwdl + dy; +operator+(const years &dy, const year_month_weekday_last &ymwdl) NOEXCEPT { + return ymwdl + dy; } CONSTCD11 inline year_month_weekday_last -operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT -{ - return ymwdl + (-dy); +operator-(const year_month_weekday_last &ymwdl, const years &dy) NOEXCEPT { + return ymwdl + (-dy); } // year_month from operator/() @@ -3310,17 +3259,15 @@ operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT CONSTCD11 inline year_month -operator/(const year& y, const month& m) NOEXCEPT -{ - return {y, m}; +operator/(const year &y, const month &m) NOEXCEPT { + return {y, m}; } CONSTCD11 inline year_month -operator/(const year& y, int m) NOEXCEPT -{ - return y / month(static_cast(m)); +operator/(const year &y, int m) NOEXCEPT { + return y / month(static_cast(m)); } // month_day from operator/() @@ -3328,69 +3275,61 @@ operator/(const year& y, int m) NOEXCEPT CONSTCD11 inline month_day -operator/(const month& m, const day& d) NOEXCEPT -{ - return {m, d}; +operator/(const month &m, const day &d) NOEXCEPT { + return {m, d}; } CONSTCD11 inline month_day -operator/(const day& d, const month& m) NOEXCEPT -{ - return m / d; +operator/(const day &d, const month &m) NOEXCEPT { + return m / d; } CONSTCD11 inline month_day -operator/(const month& m, int d) NOEXCEPT -{ - return m / day(static_cast(d)); +operator/(const month &m, int d) NOEXCEPT { + return m / day(static_cast(d)); } CONSTCD11 inline month_day -operator/(int m, const day& d) NOEXCEPT -{ - return month(static_cast(m)) / d; +operator/(int m, const day &d) NOEXCEPT { + return month(static_cast(m)) / d; } -CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;} +CONSTCD11 inline month_day operator/(const day &d, int m) NOEXCEPT {return m / d;} // month_day_last from operator/() CONSTCD11 inline month_day_last -operator/(const month& m, last_spec) NOEXCEPT -{ - return month_day_last{m}; +operator/(const month &m, last_spec) NOEXCEPT { + return month_day_last{m}; } CONSTCD11 inline month_day_last -operator/(last_spec, const month& m) NOEXCEPT -{ - return m/last; +operator/(last_spec, const month &m) NOEXCEPT { + return m / last; } CONSTCD11 inline month_day_last -operator/(int m, last_spec) NOEXCEPT -{ - return month(static_cast(m))/last; +operator/(int m, last_spec) NOEXCEPT { + return month(static_cast(m)) / last; } CONSTCD11 inline month_day_last -operator/(last_spec, int m) NOEXCEPT -{ - return m/last; +operator/(last_spec, int m) NOEXCEPT { + return m / last; } // month_weekday from operator/() @@ -3398,33 +3337,29 @@ operator/(last_spec, int m) NOEXCEPT CONSTCD11 inline month_weekday -operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT -{ - return {m, wdi}; +operator/(const month &m, const weekday_indexed &wdi) NOEXCEPT { + return {m, wdi}; } CONSTCD11 inline month_weekday -operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT -{ - return m / wdi; +operator/(const weekday_indexed &wdi, const month &m) NOEXCEPT { + return m / wdi; } CONSTCD11 inline month_weekday -operator/(int m, const weekday_indexed& wdi) NOEXCEPT -{ - return month(static_cast(m)) / wdi; +operator/(int m, const weekday_indexed &wdi) NOEXCEPT { + return month(static_cast(m)) / wdi; } CONSTCD11 inline month_weekday -operator/(const weekday_indexed& wdi, int m) NOEXCEPT -{ - return m / wdi; +operator/(const weekday_indexed &wdi, int m) NOEXCEPT { + return m / wdi; } // month_weekday_last from operator/() @@ -3432,33 +3367,29 @@ operator/(const weekday_indexed& wdi, int m) NOEXCEPT CONSTCD11 inline month_weekday_last -operator/(const month& m, const weekday_last& wdl) NOEXCEPT -{ - return {m, wdl}; +operator/(const month &m, const weekday_last &wdl) NOEXCEPT { + return {m, wdl}; } CONSTCD11 inline month_weekday_last -operator/(const weekday_last& wdl, const month& m) NOEXCEPT -{ - return m / wdl; +operator/(const weekday_last &wdl, const month &m) NOEXCEPT { + return m / wdl; } CONSTCD11 inline month_weekday_last -operator/(int m, const weekday_last& wdl) NOEXCEPT -{ - return month(static_cast(m)) / wdl; +operator/(int m, const weekday_last &wdl) NOEXCEPT { + return month(static_cast(m)) / wdl; } CONSTCD11 inline month_weekday_last -operator/(const weekday_last& wdl, int m) NOEXCEPT -{ - return m / wdl; +operator/(const weekday_last &wdl, int m) NOEXCEPT { + return m / wdl; } // year_month_day from operator/() @@ -3466,49 +3397,43 @@ operator/(const weekday_last& wdl, int m) NOEXCEPT CONSTCD11 inline year_month_day -operator/(const year_month& ym, const day& d) NOEXCEPT -{ - return {ym.year(), ym.month(), d}; +operator/(const year_month &ym, const day &d) NOEXCEPT { + return {ym.year(), ym.month(), d}; } CONSTCD11 inline year_month_day -operator/(const year_month& ym, int d) NOEXCEPT -{ - return ym / day(static_cast(d)); +operator/(const year_month &ym, int d) NOEXCEPT { + return ym / day(static_cast(d)); } CONSTCD11 inline year_month_day -operator/(const year& y, const month_day& md) NOEXCEPT -{ - return y / md.month() / md.day(); +operator/(const year &y, const month_day &md) NOEXCEPT { + return y / md.month() / md.day(); } CONSTCD11 inline year_month_day -operator/(int y, const month_day& md) NOEXCEPT -{ - return year(y) / md; +operator/(int y, const month_day &md) NOEXCEPT { + return year(y) / md; } CONSTCD11 inline year_month_day -operator/(const month_day& md, const year& y) NOEXCEPT -{ - return y / md; +operator/(const month_day &md, const year &y) NOEXCEPT { + return y / md; } CONSTCD11 inline year_month_day -operator/(const month_day& md, int y) NOEXCEPT -{ - return year(y) / md; +operator/(const month_day &md, int y) NOEXCEPT { + return year(y) / md; } // year_month_day_last from operator/() @@ -3516,41 +3441,36 @@ operator/(const month_day& md, int y) NOEXCEPT CONSTCD11 inline year_month_day_last -operator/(const year_month& ym, last_spec) NOEXCEPT -{ - return {ym.year(), month_day_last{ym.month()}}; +operator/(const year_month &ym, last_spec) NOEXCEPT { + return {ym.year(), month_day_last{ym.month()}}; } CONSTCD11 inline year_month_day_last -operator/(const year& y, const month_day_last& mdl) NOEXCEPT -{ - return {y, mdl}; +operator/(const year &y, const month_day_last &mdl) NOEXCEPT { + return {y, mdl}; } CONSTCD11 inline year_month_day_last -operator/(int y, const month_day_last& mdl) NOEXCEPT -{ - return year(y) / mdl; +operator/(int y, const month_day_last &mdl) NOEXCEPT { + return year(y) / mdl; } CONSTCD11 inline year_month_day_last -operator/(const month_day_last& mdl, const year& y) NOEXCEPT -{ - return y / mdl; +operator/(const month_day_last &mdl, const year &y) NOEXCEPT { + return y / mdl; } CONSTCD11 inline year_month_day_last -operator/(const month_day_last& mdl, int y) NOEXCEPT -{ - return year(y) / mdl; +operator/(const month_day_last &mdl, int y) NOEXCEPT { + return year(y) / mdl; } // year_month_weekday from operator/() @@ -3558,41 +3478,36 @@ operator/(const month_day_last& mdl, int y) NOEXCEPT CONSTCD11 inline year_month_weekday -operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT -{ - return {ym.year(), ym.month(), wdi}; +operator/(const year_month &ym, const weekday_indexed &wdi) NOEXCEPT { + return {ym.year(), ym.month(), wdi}; } CONSTCD11 inline year_month_weekday -operator/(const year& y, const month_weekday& mwd) NOEXCEPT -{ - return {y, mwd.month(), mwd.weekday_indexed()}; +operator/(const year &y, const month_weekday &mwd) NOEXCEPT { + return {y, mwd.month(), mwd.weekday_indexed()}; } CONSTCD11 inline year_month_weekday -operator/(int y, const month_weekday& mwd) NOEXCEPT -{ - return year(y) / mwd; +operator/(int y, const month_weekday &mwd) NOEXCEPT { + return year(y) / mwd; } CONSTCD11 inline year_month_weekday -operator/(const month_weekday& mwd, const year& y) NOEXCEPT -{ - return y / mwd; +operator/(const month_weekday &mwd, const year &y) NOEXCEPT { + return y / mwd; } CONSTCD11 inline year_month_weekday -operator/(const month_weekday& mwd, int y) NOEXCEPT -{ - return year(y) / mwd; +operator/(const month_weekday &mwd, int y) NOEXCEPT { + return year(y) / mwd; } // year_month_weekday_last from operator/() @@ -3600,64 +3515,60 @@ operator/(const month_weekday& mwd, int y) NOEXCEPT CONSTCD11 inline year_month_weekday_last -operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT -{ - return {ym.year(), ym.month(), wdl}; +operator/(const year_month &ym, const weekday_last &wdl) NOEXCEPT { + return {ym.year(), ym.month(), wdl}; } CONSTCD11 inline year_month_weekday_last -operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT -{ - return {y, mwdl.month(), mwdl.weekday_last()}; +operator/(const year &y, const month_weekday_last &mwdl) NOEXCEPT { + return {y, mwdl.month(), mwdl.weekday_last()}; } CONSTCD11 inline year_month_weekday_last -operator/(int y, const month_weekday_last& mwdl) NOEXCEPT -{ - return year(y) / mwdl; +operator/(int y, const month_weekday_last &mwdl) NOEXCEPT { + return year(y) / mwdl; } CONSTCD11 inline year_month_weekday_last -operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT -{ - return y / mwdl; +operator/(const month_weekday_last &mwdl, const year &y) NOEXCEPT { + return y / mwdl; } CONSTCD11 inline year_month_weekday_last -operator/(const month_weekday_last& mwdl, int y) NOEXCEPT -{ - return year(y) / mwdl; +operator/(const month_weekday_last &mwdl, int y) NOEXCEPT { + return year(y) / mwdl; } template struct fields; template -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, - const fields& fds, const std::string* abbrev = nullptr, - const std::chrono::seconds* offset_sec = nullptr); +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, + const fields &fds, const std::string *abbrev = nullptr, + const std::chrono::seconds *offset_sec = nullptr); template -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, - fields& fds, std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr); +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, + fields &fds, std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr); // hh_mm_ss -namespace detail -{ +namespace detail { -struct undocumented {explicit undocumented() = default;}; +struct undocumented { + explicit undocumented() = default; +}; // width::value is the number of fractional decimal digits in 1/n // width<0>::value and width<1>::value are defined to be 0 @@ -3668,322 +3579,340 @@ struct undocumented {explicit undocumented() = default;}; // Example: width<4>::value == 2 // Example: width<10>::value == 1 // Example: width<1000>::value == 3 -template -struct width -{ - static CONSTDATA unsigned value = 1 + width::value; +template < std::uint64_t n, std::uint64_t d = 10, unsigned w = 0, + bool should_continue = !(n < 2) && d != 0 && (w < 19) > +struct width { + static CONSTDATA unsigned value = 1 + width < n, d % n * 10, w + 1 >::value; }; template -struct width -{ - static CONSTDATA unsigned value = 0; +struct width { + static CONSTDATA unsigned value = 0; }; template -struct static_pow10 -{ +struct static_pow10 { private: - static CONSTDATA std::uint64_t h = static_pow10::value; + static CONSTDATA std::uint64_t h = static_pow10 < exp / 2 >::value; public: - static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1); + static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1); }; template <> -struct static_pow10<0> -{ - static CONSTDATA std::uint64_t value = 1; +struct static_pow10<0> { + static CONSTDATA std::uint64_t value = 1; }; template -class decimal_format_seconds -{ - using CT = typename std::common_type::type; - using rep = typename CT::rep; +class decimal_format_seconds { + using CT = typename std::common_type::type; + using rep = typename CT::rep; public: - static unsigned constexpr width = detail::width::value < 19 ? - detail::width::value : 6u; - using precision = std::chrono::duration::value>>; + static unsigned constexpr width = detail::width::value < 19 ? + detail::width::value : 6u; + using precision = std::chrono::duration::value>>; private: - std::chrono::seconds s_; - precision sub_s_; + std::chrono::seconds s_; + precision sub_s_; public: - CONSTCD11 decimal_format_seconds() - : s_() - , sub_s_() - {} + CONSTCD11 decimal_format_seconds() + : s_() + , sub_s_() + {} - CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT - : s_(std::chrono::duration_cast(d)) - , sub_s_(std::chrono::treat_as_floating_point::value ? d - s_ : - std::chrono::duration_cast(d - s_)) - {} + CONSTCD11 explicit decimal_format_seconds(const Duration &d) NOEXCEPT +: + s_(std::chrono::duration_cast(d)) + , sub_s_(std::chrono::treat_as_floating_point::value ? d - s_ : + std::chrono::duration_cast(d - s_)) + {} - CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;} - CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;} - CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;} + CONSTCD14 std::chrono::seconds &seconds() NOEXCEPT {return s_;} + CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT + { + return s_; + } + CONSTCD11 precision subseconds() const NOEXCEPT + { + return sub_s_; + } - CONSTCD14 precision to_duration() const NOEXCEPT - { - return s_ + sub_s_; - } + CONSTCD14 precision to_duration() const NOEXCEPT + { + return s_ + sub_s_; + } - CONSTCD11 bool in_conventional_range() const NOEXCEPT - { - return sub_s_ < std::chrono::seconds{1} && s_ < std::chrono::minutes{1}; - } + CONSTCD11 bool in_conventional_range() const NOEXCEPT + { + return sub_s_ < std::chrono::seconds{1} &&s_ < std::chrono::minutes{1}; + } - template - friend - std::basic_ostream& - operator<<(std::basic_ostream& os, const decimal_format_seconds& x) - { - return x.print(os, std::chrono::treat_as_floating_point{}); - } + template + friend + std::basic_ostream & + operator<<(std::basic_ostream &os, const decimal_format_seconds &x) + { + return x.print(os, std::chrono::treat_as_floating_point {}); + } - template - std::basic_ostream& - print(std::basic_ostream& os, std::true_type) const - { - date::detail::save_ostream _(os); - std::chrono::duration d = s_ + sub_s_; - if (d < std::chrono::seconds{10}) - os << '0'; - os << std::fixed << d.count(); - return os; - } + template + std::basic_ostream & + print(std::basic_ostream &os, std::true_type) const + { + date::detail::save_ostream _(os); + std::chrono::duration d = s_ + sub_s_; + if (d < std::chrono::seconds{10}) + os << '0'; + os << std::fixed << d.count(); + return os; + } - template - std::basic_ostream& - print(std::basic_ostream& os, std::false_type) const - { - date::detail::save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(2); - os << s_.count(); - if (width > 0) - { + template + std::basic_ostream & + print(std::basic_ostream &os, std::false_type) const + { + date::detail::save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(2); + os << s_.count(); + if (width > 0) { #if !ONLY_C_LOCALE - os << std::use_facet>(os.getloc()).decimal_point(); + os << std::use_facet>(os.getloc()).decimal_point(); #else - os << '.'; + os << '.'; #endif - os.width(width); - os << sub_s_.count(); - } - return os; + os.width(width); + os << sub_s_.count(); } + return os; + } }; template inline CONSTCD11 typename std::enable_if - < - std::numeric_limits::is_signed, - std::chrono::duration - >::type +< + std::numeric_limits::is_signed, + std::chrono::duration + >::type abs(std::chrono::duration d) { - return d >= d.zero() ? +d : -d; + return d >= d.zero() ? +d : -d; } template inline CONSTCD11 typename std::enable_if - < - !std::numeric_limits::is_signed, - std::chrono::duration - >::type +< + !std::numeric_limits::is_signed, + std::chrono::duration + >::type abs(std::chrono::duration d) { - return d; + return d; } } // namespace detail template -class hh_mm_ss -{ - using dfs = detail::decimal_format_seconds::type>; +class hh_mm_ss { + using dfs = detail::decimal_format_seconds::type>; - std::chrono::hours h_; - std::chrono::minutes m_; - dfs s_; - bool neg_; + std::chrono::hours h_; + std::chrono::minutes m_; + dfs s_; + bool neg_; public: - static unsigned CONSTDATA fractional_width = dfs::width; - using precision = typename dfs::precision; + static unsigned CONSTDATA fractional_width = dfs::width; + using precision = typename dfs::precision; - CONSTCD11 hh_mm_ss() NOEXCEPT - : hh_mm_ss(Duration::zero()) - {} + CONSTCD11 hh_mm_ss() NOEXCEPT +: + hh_mm_ss(Duration::zero()) + {} - CONSTCD11 explicit hh_mm_ss(Duration d) NOEXCEPT - : h_(std::chrono::duration_cast(detail::abs(d))) - , m_(std::chrono::duration_cast(detail::abs(d)) - h_) - , s_(detail::abs(d) - h_ - m_) - , neg_(d < Duration::zero()) - {} + CONSTCD11 explicit hh_mm_ss(Duration d) NOEXCEPT +: + h_(std::chrono::duration_cast(detail::abs(d))) + , m_(std::chrono::duration_cast(detail::abs(d)) - h_) + , s_(detail::abs(d) - h_ - m_) + , neg_(d < Duration::zero()) + {} - CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} - CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;} - CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();} - CONSTCD14 std::chrono::seconds& - seconds(detail::undocumented) NOEXCEPT {return s_.seconds();} - CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();} - CONSTCD11 bool is_negative() const NOEXCEPT {return neg_;} + CONSTCD11 std::chrono::hours hours() const NOEXCEPT + { + return h_; + } + CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT + { + return m_; + } + CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT + { + return s_.seconds(); + } + CONSTCD14 std::chrono::seconds & + seconds(detail::undocumented) NOEXCEPT {return s_.seconds();} + CONSTCD11 precision subseconds() const NOEXCEPT + { + return s_.subseconds(); + } + CONSTCD11 bool is_negative() const NOEXCEPT + { + return neg_; + } - CONSTCD11 explicit operator precision() const NOEXCEPT {return to_duration();} - CONSTCD11 precision to_duration() const NOEXCEPT - {return (h_ + m_ + s_.to_duration()) * (1-2*neg_);} + CONSTCD11 explicit operator precision() const NOEXCEPT + { + return to_duration(); + } + CONSTCD11 precision to_duration() const NOEXCEPT + { + return (h_ + m_ + s_.to_duration()) * (1 - 2 * neg_); + } - CONSTCD11 bool in_conventional_range() const NOEXCEPT - { - return !neg_ && h_ < days{1} && m_ < std::chrono::hours{1} && - s_.in_conventional_range(); - } + CONSTCD11 bool in_conventional_range() const NOEXCEPT + { + return !neg_ && h_ < days{1} &&m_ < std::chrono::hours{1} && + s_.in_conventional_range(); + } private: - template - friend - std::basic_ostream& - operator<<(std::basic_ostream& os, hh_mm_ss const& tod) - { - if (tod.is_negative()) - os << '-'; - if (tod.h_ < std::chrono::hours{10}) - os << '0'; - os << tod.h_.count() << ':'; - if (tod.m_ < std::chrono::minutes{10}) - os << '0'; - os << tod.m_.count() << ':' << tod.s_; - return os; + template + friend + std::basic_ostream & + operator<<(std::basic_ostream &os, hh_mm_ss const &tod) + { + if (tod.is_negative()) { + os << '-'; } + if (tod.h_ < std::chrono::hours{10}) + os << '0'; + os << tod.h_.count() << ':'; + if (tod.m_ < std::chrono::minutes{10}) + os << '0'; + os << tod.m_.count() << ':' << tod.s_; + return os; + } - template - friend - std::basic_ostream& - date::to_stream(std::basic_ostream& os, const CharT* fmt, - const fields& fds, const std::string* abbrev, - const std::chrono::seconds* offset_sec); + template + friend + std::basic_ostream & + date::to_stream(std::basic_ostream &os, const CharT *fmt, + const fields &fds, const std::string *abbrev, + const std::chrono::seconds *offset_sec); - template - friend - std::basic_istream& - date::from_stream(std::basic_istream& is, const CharT* fmt, - fields& fds, - std::basic_string* abbrev, std::chrono::minutes* offset); + template + friend + std::basic_istream & + date::from_stream(std::basic_istream &is, const CharT *fmt, + fields &fds, + std::basic_string *abbrev, std::chrono::minutes *offset); }; inline CONSTCD14 bool -is_am(std::chrono::hours const& h) NOEXCEPT -{ - using std::chrono::hours; - return hours{0} <= h && h < hours{12}; +is_am(std::chrono::hours const &h) NOEXCEPT { + using std::chrono::hours; + return hours{0} <= h &&h < hours{12}; } inline CONSTCD14 bool -is_pm(std::chrono::hours const& h) NOEXCEPT -{ - using std::chrono::hours; - return hours{12} <= h && h < hours{24}; +is_pm(std::chrono::hours const &h) NOEXCEPT { + using std::chrono::hours; + return hours{12} <= h &&h < hours{24}; } inline CONSTCD14 std::chrono::hours -make12(std::chrono::hours h) NOEXCEPT -{ - using std::chrono::hours; - if (h < hours{12}) - { - if (h == hours{0}) - h = hours{12}; - } - else - { - if (h != hours{12}) - h -= hours{12}; - } - return h; +make12(std::chrono::hours h) NOEXCEPT { + using std::chrono::hours; + if (h < hours{12}) + { + if (h == hours{0}) + h = hours{12}; + } + else + { + if (h != hours{12}) + h -= hours{12}; + } + return h; } inline CONSTCD14 std::chrono::hours -make24(std::chrono::hours h, bool is_pm) NOEXCEPT -{ - using std::chrono::hours; - if (is_pm) - { - if (h != hours{12}) - h += hours{12}; - } - else if (h == hours{12}) - h = hours{0}; - return h; +make24(std::chrono::hours h, bool is_pm) NOEXCEPT { + using std::chrono::hours; + if (is_pm) + { + if (h != hours{12}) + h += hours{12}; + } + else if (h == hours{12}) + h = hours{0}; + return h; } template using time_of_day = hh_mm_ss; -template ::value>::type> +template < class Rep, class Period, + class = typename std::enable_if + < !std::chrono::treat_as_floating_point::value >::type > CONSTCD11 inline hh_mm_ss> -make_time(const std::chrono::duration& d) +make_time(const std::chrono::duration &d) { - return hh_mm_ss>(d); + return hh_mm_ss>(d); } template inline typename std::enable_if < - !std::chrono::treat_as_floating_point::value && - std::ratio_less::value - , std::basic_ostream& ->::type -operator<<(std::basic_ostream& os, const sys_time& tp) + !std::chrono::treat_as_floating_point::value && + std::ratio_less::value + , std::basic_ostream & + >::type +operator<<(std::basic_ostream &os, const sys_time &tp) { - auto const dp = date::floor(tp); - return os << year_month_day(dp) << ' ' << make_time(tp-dp); + auto const dp = date::floor(tp); + return os << year_month_day(dp) << ' ' << make_time(tp - dp); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const sys_days& dp) +std::basic_ostream & +operator<<(std::basic_ostream &os, const sys_days &dp) { - return os << year_month_day(dp); + return os << year_month_day(dp); } template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, const local_time& ut) +std::basic_ostream & +operator<<(std::basic_ostream &os, const local_time &ut) { - return (os << sys_time{ut.time_since_epoch()}); + return (os << sys_time {ut.time_since_epoch()}); } -namespace detail -{ +namespace detail { template class string_literal; @@ -3991,104 +3920,119 @@ class string_literal; template inline CONSTCD14 -string_literal::type, - N1 + N2 - 1> -operator+(const string_literal& x, const string_literal& y) NOEXCEPT; +string_literal < typename std::conditional < sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2 >::type, + N1 + N2 - 1 > + operator+(const string_literal &x, const string_literal &y) NOEXCEPT; template -class string_literal -{ - CharT p_[N]; +class string_literal { + CharT p_[N]; - CONSTCD11 string_literal() NOEXCEPT - : p_{} - {} + CONSTCD11 string_literal() NOEXCEPT +: + p_{} + {} public: - using const_iterator = const CharT*; + using const_iterator = const CharT*; - string_literal(string_literal const&) = default; - string_literal& operator=(string_literal const&) = delete; + string_literal(string_literal const &) = default; + string_literal &operator=(string_literal const &) = delete; - template ::type> - CONSTCD11 string_literal(CharT c) NOEXCEPT - : p_{c} + template ::type> + CONSTCD11 string_literal(CharT c) NOEXCEPT +: + p_{c} { + } + + template ::type> + CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT +: + p_{c1, c2} { + } + + template ::type> + CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT +: + p_{c1, c2, c3} { + } + + CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT +: + p_{} { + for (std::size_t i = 0; i < N; ++i) { + p_[i] = a[i]; } + } - template ::type> - CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT - : p_{c1, c2} - { + template < class U = CharT, + class = typename std::enable_if<(1 < sizeof(U))>::type> + CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT + : p_ {} + { + for (std::size_t i = 0; i < N; ++i) { + p_[i] = a[i]; } + } - template ::type> - CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT - : p_{c1, c2, c3} - { + template < class CharT2, + class = typename std::enable_if < !std::is_same::value >::type > + CONSTCD14 string_literal(string_literal const &a) NOEXCEPT +: p_ {} + { + for (std::size_t i = 0; i < N; ++i) { + p_[i] = a[i]; } + } - CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT - : p_{} - { - for (std::size_t i = 0; i < N; ++i) - p_[i] = a[i]; - } + CONSTCD11 const CharT *data() const NOEXCEPT + { + return p_; + } + CONSTCD11 std::size_t size() const NOEXCEPT + { + return N - 1; + } - template ::type> - CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT - : p_{} - { - for (std::size_t i = 0; i < N; ++i) - p_[i] = a[i]; - } + CONSTCD11 const_iterator begin() const NOEXCEPT + { + return p_; + } + CONSTCD11 const_iterator end() const NOEXCEPT + { + return p_ + N - 1; + } - template ::value>::type> - CONSTCD14 string_literal(string_literal const& a) NOEXCEPT - : p_{} - { - for (std::size_t i = 0; i < N; ++i) - p_[i] = a[i]; - } + CONSTCD11 CharT const &operator[](std::size_t n) const NOEXCEPT + { + return p_[n]; + } - CONSTCD11 const CharT* data() const NOEXCEPT {return p_;} - CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;} + template + friend + std::basic_ostream & + operator<<(std::basic_ostream &os, const string_literal &s) + { + return os << s.p_; + } - CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;} - CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;} - - CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT - { - return p_[n]; - } - - template - friend - std::basic_ostream& - operator<<(std::basic_ostream& os, const string_literal& s) - { - return os << s.p_; - } - - template - friend - CONSTCD14 - string_literal::type, - N1 + N2 - 1> - operator+(const string_literal& x, const string_literal& y) NOEXCEPT; + template + friend + CONSTCD14 + string_literal < typename std::conditional < sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2 >::type, + N1 + N2 - 1 > + operator+(const string_literal &x, const string_literal &y) NOEXCEPT; }; template CONSTCD11 inline string_literal -operator+(const string_literal& x, const string_literal& y) NOEXCEPT -{ +operator+(const string_literal &x, const string_literal &y) NOEXCEPT { return string_literal(x[0], y[0]); } @@ -4096,54 +4040,55 @@ template CONSTCD11 inline string_literal -operator+(const string_literal& x, const string_literal& y) NOEXCEPT -{ +operator+(const string_literal &x, const string_literal &y) NOEXCEPT { return string_literal(x[0], x[1], y[0]); } template CONSTCD14 inline -string_literal::type, - N1 + N2 - 1> -operator+(const string_literal& x, const string_literal& y) NOEXCEPT -{ - using CT = typename std::conditional::type; +string_literal < typename std::conditional < sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2 >::type, + N1 + N2 - 1 > +operator+(const string_literal &x, const string_literal &y) NOEXCEPT { + using CT = typename std::conditional < sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2 >::type; - string_literal r; - std::size_t i = 0; - for (; i < N1-1; ++i) - r.p_[i] = CT(x.p_[i]); - for (std::size_t j = 0; j < N2; ++j, ++i) - r.p_[i] = CT(y.p_[j]); + string_literal < CT, N1 + N2 - 1 > r; + std::size_t i = 0; + for (; i < N1 - 1; ++i) + { + r.p_[i] = CT(x.p_[i]); + } + for (std::size_t j = 0; j < N2; ++j, ++i) + { + r.p_[i] = CT(y.p_[j]); + } - return r; + return r; } template inline std::basic_string -operator+(std::basic_string x, const string_literal& y) +operator+(std::basic_string x, const string_literal &y) { - x.append(y.data(), y.size()); - return x; + x.append(y.data(), y.size()); + return x; } #if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \ && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150) -template {} || - std::is_same{} || - std::is_same{} || - std::is_same{}>> -CONSTCD14 -inline -string_literal -msl(CharT c) NOEXCEPT -{ - return string_literal{c}; +template < class CharT, +class = std::enable_if_t < std::is_same {} || +std::is_same {} || +std::is_same {} || +std::is_same {} >> + CONSTCD14 + inline + string_literal +msl(CharT c) NOEXCEPT { + return string_literal{c}; } CONSTCD14 @@ -4151,13 +4096,13 @@ inline std::size_t to_string_len(std::intmax_t i) { - std::size_t r = 0; - do - { - i /= 10; - ++r; - } while (i > 0); - return r; + std::size_t r = 0; + do { + i /= 10; + ++r; + } + while (i > 0); + return r; } template @@ -4165,12 +4110,11 @@ CONSTCD14 inline std::enable_if_t < - N < 10, - string_literal -> -msl() NOEXCEPT -{ - return msl(char(N % 10 + '0')); + N < 10, + string_literal < char, to_string_len(N) + 1 > + > +msl() NOEXCEPT { + return msl(char(N % 10 + '0')); } template @@ -4178,12 +4122,11 @@ CONSTCD14 inline std::enable_if_t < - 10 <= N, - string_literal -> -msl() NOEXCEPT -{ - return msl() + msl(char(N % 10 + '0')); + 10 <= N, + string_literal < char, to_string_len(N) + 1 > + > +msl() NOEXCEPT { + return msl < N / 10 > () + msl(char(N % 10 + '0')); } template @@ -4191,15 +4134,14 @@ CONSTCD14 inline std::enable_if_t < - std::ratio::type::den != 1, - string_literal::type::num) + - to_string_len(std::ratio::type::den) + 4> -> -msl(std::ratio) NOEXCEPT -{ - using R = typename std::ratio::type; - return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + - msl() + msl(CharT{']'}); + std::ratio::type::den != 1, + string_literal < CharT, to_string_len(std::ratio::type::num) + + to_string_len(std::ratio::type::den) + 4 > + > +msl(std::ratio) NOEXCEPT { + using R = typename std::ratio::type; + return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + + msl() + msl(CharT{']'}); } template @@ -4207,13 +4149,12 @@ CONSTCD14 inline std::enable_if_t < - std::ratio::type::den == 1, - string_literal::type::num) + 3> -> -msl(std::ratio) NOEXCEPT -{ - using R = typename std::ratio::type; - return msl(CharT{'['}) + msl() + msl(CharT{']'}); + std::ratio::type::den == 1, + string_literal < CharT, to_string_len(std::ratio::type::num) + 3 > + > +msl(std::ratio) NOEXCEPT { + using R = typename std::ratio::type; + return msl(CharT{'['}) + msl() + msl(CharT{']'}); } @@ -4223,7 +4164,7 @@ inline std::string to_string(std::uint64_t x) { - return std::to_string(x); + return std::to_string(x); } template @@ -4231,35 +4172,35 @@ inline std::basic_string to_string(std::uint64_t x) { - auto y = std::to_string(x); - return std::basic_string(y.begin(), y.end()); + auto y = std::to_string(x); + return std::basic_string(y.begin(), y.end()); } template inline typename std::enable_if < - std::ratio::type::den != 1, - std::basic_string ->::type + std::ratio::type::den != 1, + std::basic_string + >::type msl(std::ratio) { - using R = typename std::ratio::type; - return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + - to_string(R::den) + CharT{']'}; + using R = typename std::ratio::type; + return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + + to_string(R::den) + CharT{']'}; } template inline typename std::enable_if < - std::ratio::type::den == 1, - std::basic_string ->::type + std::ratio::type::den == 1, + std::basic_string + >::type msl(std::ratio) { - using R = typename std::ratio::type; - return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; + using R = typename std::ratio::type; + return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; } #endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) @@ -4268,36 +4209,32 @@ template CONSTCD11 inline string_literal -msl(std::atto) NOEXCEPT -{ - return string_literal{'a'}; +msl(std::atto) NOEXCEPT { + return string_literal{'a'}; } template CONSTCD11 inline string_literal -msl(std::femto) NOEXCEPT -{ - return string_literal{'f'}; +msl(std::femto) NOEXCEPT { + return string_literal{'f'}; } template CONSTCD11 inline string_literal -msl(std::pico) NOEXCEPT -{ - return string_literal{'p'}; +msl(std::pico) NOEXCEPT { + return string_literal{'p'}; } template CONSTCD11 inline string_literal -msl(std::nano) NOEXCEPT -{ - return string_literal{'n'}; +msl(std::nano) NOEXCEPT { + return string_literal{'n'}; } template @@ -4305,12 +4242,11 @@ CONSTCD11 inline typename std::enable_if < - std::is_same::value, - string_literal ->::type -msl(std::micro) NOEXCEPT -{ - return string_literal{'\xC2', '\xB5'}; + std::is_same::value, + string_literal + >::type +msl(std::micro) NOEXCEPT { + return string_literal{'\xC2', '\xB5'}; } template @@ -4318,111 +4254,99 @@ CONSTCD11 inline typename std::enable_if < - !std::is_same::value, - string_literal ->::type -msl(std::micro) NOEXCEPT -{ - return string_literal{CharT{static_cast('\xB5')}}; + !std::is_same::value, + string_literal + >::type +msl(std::micro) NOEXCEPT { + return string_literal{CharT{static_cast('\xB5')}}; } template CONSTCD11 inline string_literal -msl(std::milli) NOEXCEPT -{ - return string_literal{'m'}; +msl(std::milli) NOEXCEPT { + return string_literal{'m'}; } template CONSTCD11 inline string_literal -msl(std::centi) NOEXCEPT -{ - return string_literal{'c'}; +msl(std::centi) NOEXCEPT { + return string_literal{'c'}; } template CONSTCD11 inline string_literal -msl(std::deca) NOEXCEPT -{ - return string_literal{'d', 'a'}; +msl(std::deca) NOEXCEPT { + return string_literal{'d', 'a'}; } template CONSTCD11 inline string_literal -msl(std::deci) NOEXCEPT -{ - return string_literal{'d'}; +msl(std::deci) NOEXCEPT { + return string_literal{'d'}; } template CONSTCD11 inline string_literal -msl(std::hecto) NOEXCEPT -{ - return string_literal{'h'}; +msl(std::hecto) NOEXCEPT { + return string_literal{'h'}; } template CONSTCD11 inline string_literal -msl(std::kilo) NOEXCEPT -{ - return string_literal{'k'}; +msl(std::kilo) NOEXCEPT { + return string_literal{'k'}; } template CONSTCD11 inline string_literal -msl(std::mega) NOEXCEPT -{ - return string_literal{'M'}; +msl(std::mega) NOEXCEPT { + return string_literal{'M'}; } template CONSTCD11 inline string_literal -msl(std::giga) NOEXCEPT -{ - return string_literal{'G'}; +msl(std::giga) NOEXCEPT { + return string_literal{'G'}; } template CONSTCD11 inline string_literal -msl(std::tera) NOEXCEPT -{ - return string_literal{'T'}; +msl(std::tera) NOEXCEPT { + return string_literal{'T'}; } template CONSTCD11 inline string_literal -msl(std::peta) NOEXCEPT -{ - return string_literal{'P'}; +msl(std::peta) NOEXCEPT { + return string_literal{'P'}; } template CONSTCD11 inline string_literal -msl(std::exa) NOEXCEPT -{ - return string_literal{'E'}; +msl(std::exa) NOEXCEPT { + return string_literal{'E'}; } template @@ -4430,9 +4354,9 @@ CONSTCD11 inline auto get_units(Period p) - -> decltype(msl(p) + string_literal{'s'}) +-> decltype(msl(p) + string_literal {'s'}) { - return msl(p) + string_literal{'s'}; + return msl(p) + string_literal {'s'}; } template @@ -4441,7 +4365,7 @@ inline string_literal get_units(std::ratio<1>) { - return string_literal{'s'}; + return string_literal {'s'}; } template @@ -4450,7 +4374,7 @@ inline string_literal get_units(std::ratio<3600>) { - return string_literal{'h'}; + return string_literal {'h'}; } template @@ -4459,7 +4383,7 @@ inline string_literal get_units(std::ratio<60>) { - return string_literal{'m', 'i', 'n'}; + return string_literal {'m', 'i', 'n'}; } template @@ -4468,60 +4392,56 @@ inline string_literal get_units(std::ratio<86400>) { - return string_literal{'d'}; + return string_literal {'d'}; } template > struct make_string; template <> -struct make_string -{ - template - static - std::string - from(Rep n) - { - return std::to_string(n); - } +struct make_string { + template + static + std::string + from(Rep n) + { + return std::to_string(n); + } }; template -struct make_string -{ - template - static - std::basic_string - from(Rep n) - { - auto s = std::to_string(n); - return std::basic_string(s.begin(), s.end()); - } +struct make_string { + template + static + std::basic_string + from(Rep n) + { + auto s = std::to_string(n); + return std::basic_string(s.begin(), s.end()); + } }; template <> -struct make_string -{ - template - static - std::wstring - from(Rep n) - { - return std::to_wstring(n); - } +struct make_string { + template + static + std::wstring + from(Rep n) + { + return std::to_wstring(n); + } }; template -struct make_string -{ - template - static - std::basic_string - from(Rep n) - { - auto s = std::to_wstring(n); - return std::basic_string(s.begin(), s.end()); - } +struct make_string { + template + static + std::basic_string + from(Rep n) + { + auto s = std::to_wstring(n); + return std::basic_string(s.begin(), s.end()); + } }; } // namespace detail @@ -4531,254 +4451,235 @@ struct make_string CONSTDATA year nanyear{-32768}; template -struct fields -{ - year_month_day ymd{nanyear/0/0}; - weekday wd{8u}; - hh_mm_ss tod{}; - bool has_tod = false; +struct fields { + year_month_day ymd{nanyear / 0 / 0}; + weekday wd{8u}; + hh_mm_ss tod{}; + bool has_tod = false; - fields() = default; + fields() = default; - fields(year_month_day ymd_) : ymd(ymd_) {} - fields(weekday wd_) : wd(wd_) {} - fields(hh_mm_ss tod_) : tod(tod_), has_tod(true) {} + fields(year_month_day ymd_) : ymd(ymd_) {} + fields(weekday wd_) : wd(wd_) {} + fields(hh_mm_ss tod_) : tod(tod_), has_tod(true) {} - fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {} - fields(year_month_day ymd_, hh_mm_ss tod_) : ymd(ymd_), tod(tod_), - has_tod(true) {} + fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {} + fields(year_month_day ymd_, hh_mm_ss tod_) : ymd(ymd_), tod(tod_), + has_tod(true) {} - fields(weekday wd_, hh_mm_ss tod_) : wd(wd_), tod(tod_), has_tod(true) {} + fields(weekday wd_, hh_mm_ss tod_) : wd(wd_), tod(tod_), has_tod(true) {} - fields(year_month_day ymd_, weekday wd_, hh_mm_ss tod_) - : ymd(ymd_) - , wd(wd_) - , tod(tod_) - , has_tod(true) - {} + fields(year_month_day ymd_, weekday wd_, hh_mm_ss tod_) + : ymd(ymd_) + , wd(wd_) + , tod(tod_) + , has_tod(true) + {} }; -namespace detail -{ +namespace detail { template unsigned -extract_weekday(std::basic_ostream& os, const fields& fds) +extract_weekday(std::basic_ostream &os, const fields &fds) { - if (!fds.ymd.ok() && !fds.wd.ok()) - { - // fds does not contain a valid weekday - os.setstate(std::ios::failbit); - return 8; + if (!fds.ymd.ok() && !fds.wd.ok()) { + // fds does not contain a valid weekday + os.setstate(std::ios::failbit); + return 8; + } + weekday wd; + if (fds.ymd.ok()) { + wd = weekday{sys_days(fds.ymd)}; + if (fds.wd.ok() && wd != fds.wd) { + // fds.ymd and fds.wd are inconsistent + os.setstate(std::ios::failbit); + return 8; } - weekday wd; - if (fds.ymd.ok()) - { - wd = weekday{sys_days(fds.ymd)}; - if (fds.wd.ok() && wd != fds.wd) - { - // fds.ymd and fds.wd are inconsistent - os.setstate(std::ios::failbit); - return 8; - } - } - else - wd = fds.wd; - return static_cast((wd - Sunday).count()); + } + else { + wd = fds.wd; + } + return static_cast((wd - Sunday).count()); } template unsigned -extract_month(std::basic_ostream& os, const fields& fds) +extract_month(std::basic_ostream &os, const fields &fds) { - if (!fds.ymd.month().ok()) - { - // fds does not contain a valid month - os.setstate(std::ios::failbit); - return 0; - } - return static_cast(fds.ymd.month()); + if (!fds.ymd.month().ok()) { + // fds does not contain a valid month + os.setstate(std::ios::failbit); + return 0; + } + return static_cast(fds.ymd.month()); } } // namespace detail #if ONLY_C_LOCALE -namespace detail -{ +namespace detail { inline -std::pair +std::pair weekday_names() { - static const std::string nm[] = - { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sun", - "Mon", - "Tue", - "Wed", - "Thu", - "Fri", - "Sat" - }; - return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); + static const std::string nm[] = { + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + }; + return std::make_pair(nm, nm + sizeof(nm) / sizeof(nm[0])); } inline -std::pair +std::pair month_names() { - static const std::string nm[] = - { - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec" - }; - return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); + static const std::string nm[] = { + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + return std::make_pair(nm, nm + sizeof(nm) / sizeof(nm[0])); } inline -std::pair +std::pair ampm_names() { - static const std::string nm[] = - { - "AM", - "PM" - }; - return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); + static const std::string nm[] = { + "AM", + "PM" + }; + return std::make_pair(nm, nm + sizeof(nm) / sizeof(nm[0])); } template FwdIter -scan_keyword(std::basic_istream& is, FwdIter kb, FwdIter ke) +scan_keyword(std::basic_istream &is, FwdIter kb, FwdIter ke) { - size_t nkw = static_cast(std::distance(kb, ke)); - const unsigned char doesnt_match = '\0'; - const unsigned char might_match = '\1'; - const unsigned char does_match = '\2'; - unsigned char statbuf[100]; - unsigned char* status = statbuf; - std::unique_ptr stat_hold(0, free); - if (nkw > sizeof(statbuf)) - { - status = (unsigned char*)std::malloc(nkw); - if (status == nullptr) - throw std::bad_alloc(); - stat_hold.reset(status); + size_t nkw = static_cast(std::distance(kb, ke)); + const unsigned char doesnt_match = '\0'; + const unsigned char might_match = '\1'; + const unsigned char does_match = '\2'; + unsigned char statbuf[100]; + unsigned char *status = statbuf; + std::unique_ptr stat_hold(0, free); + if (nkw > sizeof(statbuf)) { + status = (unsigned char *)std::malloc(nkw); + if (status == nullptr) { + throw std::bad_alloc(); } - size_t n_might_match = nkw; // At this point, any keyword might match - size_t n_does_match = 0; // but none of them definitely do - // Initialize all statuses to might_match, except for "" keywords are does_match - unsigned char* st = status; - for (auto ky = kb; ky != ke; ++ky, ++st) - { - if (!ky->empty()) - *st = might_match; - else - { + stat_hold.reset(status); + } + size_t n_might_match = nkw; // At this point, any keyword might match + size_t n_does_match = 0; // but none of them definitely do + // Initialize all statuses to might_match, except for "" keywords are does_match + unsigned char *st = status; + for (auto ky = kb; ky != ke; ++ky, ++st) { + if (!ky->empty()) { + *st = might_match; + } + else { + *st = does_match; + --n_might_match; + ++n_does_match; + } + } + // While there might be a match, test keywords against the next CharT + for (size_t indx = 0; is && n_might_match > 0; ++indx) { + // Peek at the next CharT but don't consume it + auto ic = is.peek(); + if (ic == EOF) { + is.setstate(std::ios::eofbit); + break; + } + auto c = static_cast(toupper(ic)); + bool consume = false; + // For each keyword which might match, see if the indx character is c + // If a match if found, consume c + // If a match is found, and that is the last character in the keyword, + // then that keyword matches. + // If the keyword doesn't match this character, then change the keyword + // to doesn't match + st = status; + for (auto ky = kb; ky != ke; ++ky, ++st) { + if (*st == might_match) { + if (c == static_cast(toupper((*ky)[indx]))) { + consume = true; + if (ky->size() == indx + 1) { *st = does_match; --n_might_match; ++n_does_match; + } } + else { + *st = doesnt_match; + --n_might_match; + } + } } - // While there might be a match, test keywords against the next CharT - for (size_t indx = 0; is && n_might_match > 0; ++indx) - { - // Peek at the next CharT but don't consume it - auto ic = is.peek(); - if (ic == EOF) - { - is.setstate(std::ios::eofbit); - break; - } - auto c = static_cast(toupper(ic)); - bool consume = false; - // For each keyword which might match, see if the indx character is c - // If a match if found, consume c - // If a match is found, and that is the last character in the keyword, - // then that keyword matches. - // If the keyword doesn't match this character, then change the keyword - // to doesn't match + // consume if we matched a character + if (consume) { + (void)is.get(); + // If we consumed a character and there might be a matched keyword that + // was marked matched on a previous iteration, then such keywords + // are now marked as not matching. + if (n_might_match + n_does_match > 1) { st = status; - for (auto ky = kb; ky != ke; ++ky, ++st) - { - if (*st == might_match) - { - if (c == static_cast(toupper((*ky)[indx]))) - { - consume = true; - if (ky->size() == indx+1) - { - *st = does_match; - --n_might_match; - ++n_does_match; - } - } - else - { - *st = doesnt_match; - --n_might_match; - } - } - } - // consume if we matched a character - if (consume) - { - (void)is.get(); - // If we consumed a character and there might be a matched keyword that - // was marked matched on a previous iteration, then such keywords - // are now marked as not matching. - if (n_might_match + n_does_match > 1) - { - st = status; - for (auto ky = kb; ky != ke; ++ky, ++st) - { - if (*st == does_match && ky->size() != indx+1) - { - *st = doesnt_match; - --n_does_match; - } - } - } + for (auto ky = kb; ky != ke; ++ky, ++st) { + if (*st == does_match && ky->size() != indx + 1) { + *st = doesnt_match; + --n_does_match; + } } + } } - // We've exited the loop because we hit eof and/or we have no more "might matches". - // Return the first matching result - for (st = status; kb != ke; ++kb, ++st) - if (*st == does_match) - break; - if (kb == ke) - is.setstate(std::ios::failbit); - return kb; + } + // We've exited the loop because we hit eof and/or we have no more "might matches". + // Return the first matching result + for (st = status; kb != ke; ++kb, ++st) + if (*st == does_match) { + break; + } + if (kb == ke) { + is.setstate(std::ios::failbit); + } + return kb; } } // namespace detail @@ -4786,3076 +4687,3036 @@ scan_keyword(std::basic_istream& is, FwdIter kb, FwdIter ke) #endif // ONLY_C_LOCALE template -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, - const fields& fds, const std::string* abbrev, - const std::chrono::seconds* offset_sec) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, + const fields &fds, const std::string *abbrev, + const std::chrono::seconds *offset_sec) { #if ONLY_C_LOCALE - using detail::weekday_names; - using detail::month_names; - using detail::ampm_names; + using detail::weekday_names; + using detail::month_names; + using detail::ampm_names; #endif - using detail::save_ostream; - using detail::get_units; - using detail::extract_weekday; - using detail::extract_month; - using std::ios; - using std::chrono::duration_cast; - using std::chrono::seconds; - using std::chrono::minutes; - using std::chrono::hours; - date::detail::save_ostream ss(os); - os.fill(' '); - os.flags(std::ios::skipws | std::ios::dec); - os.width(0); - tm tm{}; - bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero(); + using detail::save_ostream; + using detail::get_units; + using detail::extract_weekday; + using detail::extract_month; + using std::ios; + using std::chrono::duration_cast; + using std::chrono::seconds; + using std::chrono::minutes; + using std::chrono::hours; + date::detail::save_ostream ss(os); + os.fill(' '); + os.flags(std::ios::skipws | std::ios::dec); + os.width(0); + tm tm{}; + bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero(); #if !ONLY_C_LOCALE - auto& facet = std::use_facet>(os.getloc()); + auto &facet = std::use_facet>(os.getloc()); #endif - const CharT* command = nullptr; - CharT modified = CharT{}; - for (; *fmt; ++fmt) - { - switch (*fmt) - { - case 'a': - case 'A': - if (command) - { - if (modified == CharT{}) - { - tm.tm_wday = static_cast(extract_weekday(os, fds)); - if (os.fail()) - return os; + const CharT *command = nullptr; + CharT modified = CharT{}; + for (; *fmt; ++fmt) { + switch (*fmt) { + case 'a': + case 'A': + if (command) { + if (modified == CharT{}) { + tm.tm_wday = static_cast(extract_weekday(os, fds)); + if (os.fail()) { + return os; + } #if !ONLY_C_LOCALE - const CharT f[] = {'%', *fmt}; - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + const CharT f[] = {'%', *fmt}; + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); #else // ONLY_C_LOCALE - os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')]; + os << weekday_names().first[tm.tm_wday + 7 * (*fmt == 'a')]; #endif // ONLY_C_LOCALE - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'b': - case 'B': - case 'h': - if (command) - { - if (modified == CharT{}) - { - tm.tm_mon = static_cast(extract_month(os, fds)) - 1; -#if !ONLY_C_LOCALE - const CharT f[] = {'%', *fmt}; - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); -#else // ONLY_C_LOCALE - os << month_names().first[tm.tm_mon+12*(*fmt != 'B')]; -#endif // ONLY_C_LOCALE - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'c': - case 'x': - if (command) - { - if (modified == CharT{'O'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.ymd.ok()) - os.setstate(std::ios::failbit); - if (*fmt == 'c' && !fds.has_tod) - os.setstate(std::ios::failbit); -#if !ONLY_C_LOCALE - tm = std::tm{}; - auto const& ymd = fds.ymd; - auto ld = local_days(ymd); - if (*fmt == 'c') - { - tm.tm_sec = static_cast(fds.tod.seconds().count()); - tm.tm_min = static_cast(fds.tod.minutes().count()); - tm.tm_hour = static_cast(fds.tod.hours().count()); - } - tm.tm_mday = static_cast(static_cast(ymd.day())); - tm.tm_mon = static_cast(extract_month(os, fds) - 1); - tm.tm_year = static_cast(ymd.year()) - 1900; - tm.tm_wday = static_cast(extract_weekday(os, fds)); - if (os.fail()) - return os; - tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); - CharT f[3] = {'%'}; - auto fe = std::begin(f) + 1; - if (modified == CharT{'E'}) - *fe++ = modified; - *fe++ = *fmt; - facet.put(os, os, os.fill(), &tm, std::begin(f), fe); -#else // ONLY_C_LOCALE - if (*fmt == 'c') - { - auto wd = static_cast(extract_weekday(os, fds)); - os << weekday_names().first[static_cast(wd)+7] - << ' '; - os << month_names().first[extract_month(os, fds)-1+12] << ' '; - auto d = static_cast(static_cast(fds.ymd.day())); - if (d < 10) - os << ' '; - os << d << ' ' - << make_time(duration_cast(fds.tod.to_duration())) - << ' ' << fds.ymd.year(); - - } - else // *fmt == 'x' - { - auto const& ymd = fds.ymd; - save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(2); - os << static_cast(ymd.month()) << CharT{'/'}; - os.width(2); - os << static_cast(ymd.day()) << CharT{'/'}; - os.width(2); - os << static_cast(ymd.year()) % 100; - } -#endif // ONLY_C_LOCALE - } - command = nullptr; - modified = CharT{}; - } - else - os << *fmt; - break; - case 'C': - if (command) - { - if (modified == CharT{'O'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.ymd.year().ok()) - os.setstate(std::ios::failbit); - auto y = static_cast(fds.ymd.year()); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - if (y >= 0) - { - os.width(2); - os << y/100; - } - else - { - os << CharT{'-'}; - os.width(2); - os << -(y-99)/100; - } - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'E'}) - { - tm.tm_year = y - 1900; - CharT f[3] = {'%', 'E', 'C'}; - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - command = nullptr; - modified = CharT{}; - } - else - os << *fmt; - break; - case 'd': - case 'e': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.ymd.day().ok()) - os.setstate(std::ios::failbit); - auto d = static_cast(static_cast(fds.ymd.day())); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - save_ostream _(os); - if (*fmt == CharT{'d'}) - os.fill('0'); - else - os.fill(' '); - os.flags(std::ios::dec | std::ios::right); - os.width(2); - os << d; - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - tm.tm_mday = d; - CharT f[3] = {'%', 'O', *fmt}; - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - command = nullptr; - modified = CharT{}; - } - else - os << *fmt; - break; - case 'D': - if (command) - { - if (modified == CharT{}) - { - if (!fds.ymd.ok()) - os.setstate(std::ios::failbit); - auto const& ymd = fds.ymd; - save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(2); - os << static_cast(ymd.month()) << CharT{'/'}; - os.width(2); - os << static_cast(ymd.day()) << CharT{'/'}; - os.width(2); - os << static_cast(ymd.year()) % 100; - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'F': - if (command) - { - if (modified == CharT{}) - { - if (!fds.ymd.ok()) - os.setstate(std::ios::failbit); - auto const& ymd = fds.ymd; - save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(4); - os << static_cast(ymd.year()) << CharT{'-'}; - os.width(2); - os << static_cast(ymd.month()) << CharT{'-'}; - os.width(2); - os << static_cast(ymd.day()); - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'g': - case 'G': - if (command) - { - if (modified == CharT{}) - { - if (!fds.ymd.ok()) - os.setstate(std::ios::failbit); - auto ld = local_days(fds.ymd); - auto y = year_month_day{ld + days{3}}.year(); - auto start = local_days((y-years{1})/December/Thursday[last]) + - (Monday-Thursday); - if (ld < start) - --y; - if (*fmt == CharT{'G'}) - os << y; - else - { - save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(2); - os << std::abs(static_cast(y)) % 100; - } - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'H': - case 'I': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); - if (insert_negative) - { - os << '-'; - insert_negative = false; - } - auto hms = fds.tod; -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - auto h = *fmt == CharT{'I'} ? make12(hms.hours()) : hms.hours(); - if (h < hours{10}) - os << CharT{'0'}; - os << h.count(); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_hour = static_cast(hms.hours().count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'j': - if (command) - { - if (modified == CharT{}) - { - if (fds.ymd.ok() || fds.has_tod) - { - days doy; - if (fds.ymd.ok()) - { - auto ld = local_days(fds.ymd); - auto y = fds.ymd.year(); - doy = ld - local_days(y/January/1) + days{1}; - } - else - { - doy = duration_cast(fds.tod.to_duration()); - } - save_ostream _(os); - os.fill('0'); - os.flags(std::ios::dec | std::ios::right); - os.width(3); - os << doy.count(); - } - else - { - os.setstate(std::ios::failbit); - } - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'm': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.ymd.month().ok()) - os.setstate(std::ios::failbit); - auto m = static_cast(fds.ymd.month()); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - if (m < 10) - os << CharT{'0'}; - os << m; - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_mon = static_cast(m-1); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'M': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); - if (insert_negative) - { - os << '-'; - insert_negative = false; - } -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - if (fds.tod.minutes() < minutes{10}) - os << CharT{'0'}; - os << fds.tod.minutes().count(); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_min = static_cast(fds.tod.minutes().count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'n': - if (command) - { - if (modified == CharT{}) - os << CharT{'\n'}; - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'p': - if (command) - { - if (modified == CharT{}) - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); -#if !ONLY_C_LOCALE - const CharT f[] = {'%', *fmt}; - tm.tm_hour = static_cast(fds.tod.hours().count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); -#else - if (is_am(fds.tod.hours())) - os << ampm_names().first[0]; - else - os << ampm_names().first[1]; -#endif - } - else - { - os << CharT{'%'} << modified << *fmt; - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'Q': - case 'q': - if (command) - { - if (modified == CharT{}) - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); - auto d = fds.tod.to_duration(); - if (*fmt == 'q') - os << get_units(typename decltype(d)::period::type{}); - else - os << d.count(); - } - else - { - os << CharT{'%'} << modified << *fmt; - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'r': - if (command) - { - if (modified == CharT{}) - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); -#if !ONLY_C_LOCALE - const CharT f[] = {'%', *fmt}; - tm.tm_hour = static_cast(fds.tod.hours().count()); - tm.tm_min = static_cast(fds.tod.minutes().count()); - tm.tm_sec = static_cast(fds.tod.seconds().count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); -#else - hh_mm_ss tod(duration_cast(fds.tod.to_duration())); - save_ostream _(os); - os.fill('0'); - os.width(2); - os << make12(tod.hours()).count() << CharT{':'}; - os.width(2); - os << tod.minutes().count() << CharT{':'}; - os.width(2); - os << tod.seconds().count() << CharT{' '}; - if (is_am(tod.hours())) - os << ampm_names().first[0]; - else - os << ampm_names().first[1]; -#endif - } - else - { - os << CharT{'%'} << modified << *fmt; - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'R': - if (command) - { - if (modified == CharT{}) - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); - if (fds.tod.hours() < hours{10}) - os << CharT{'0'}; - os << fds.tod.hours().count() << CharT{':'}; - if (fds.tod.minutes() < minutes{10}) - os << CharT{'0'}; - os << fds.tod.minutes().count(); - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'S': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); - if (insert_negative) - { - os << '-'; - insert_negative = false; - } -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - os << fds.tod.s_; - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_sec = static_cast(fds.tod.s_.seconds().count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 't': - if (command) - { - if (modified == CharT{}) - os << CharT{'\t'}; - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'T': - if (command) - { - if (modified == CharT{}) - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); - os << fds.tod; - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'u': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - auto wd = extract_weekday(os, fds); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - os << (wd != 0 ? wd : 7u); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_wday = static_cast(wd); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'U': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - auto const& ymd = fds.ymd; - if (!ymd.ok()) - os.setstate(std::ios::failbit); - auto ld = local_days(ymd); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - auto st = local_days(Sunday[1]/January/ymd.year()); - if (ld < st) - os << CharT{'0'} << CharT{'0'}; - else - { - auto wn = duration_cast(ld - st).count() + 1; - if (wn < 10) - os << CharT{'0'}; - os << wn; - } - } - #if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_year = static_cast(ymd.year()) - 1900; - tm.tm_wday = static_cast(extract_weekday(os, fds)); - if (os.fail()) - return os; - tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'V': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.ymd.ok()) - os.setstate(std::ios::failbit); - auto ld = local_days(fds.ymd); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - auto y = year_month_day{ld + days{3}}.year(); - auto st = local_days((y-years{1})/12/Thursday[last]) + - (Monday-Thursday); - if (ld < st) - { - --y; - st = local_days((y - years{1})/12/Thursday[last]) + - (Monday-Thursday); - } - auto wn = duration_cast(ld - st).count() + 1; - if (wn < 10) - os << CharT{'0'}; - os << wn; - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - auto const& ymd = fds.ymd; - tm.tm_year = static_cast(ymd.year()) - 1900; - tm.tm_wday = static_cast(extract_weekday(os, fds)); - if (os.fail()) - return os; - tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'w': - if (command) - { - auto wd = extract_weekday(os, fds); - if (os.fail()) - return os; -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - os << wd; - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_wday = static_cast(wd); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - else - { - os << CharT{'%'} << modified << *fmt; - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'W': - if (command) - { - if (modified == CharT{'E'}) - os << CharT{'%'} << modified << *fmt; - else - { - auto const& ymd = fds.ymd; - if (!ymd.ok()) - os.setstate(std::ios::failbit); - auto ld = local_days(ymd); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - auto st = local_days(Monday[1]/January/ymd.year()); - if (ld < st) - os << CharT{'0'} << CharT{'0'}; - else - { - auto wn = duration_cast(ld - st).count() + 1; - if (wn < 10) - os << CharT{'0'}; - os << wn; - } - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_year = static_cast(ymd.year()) - 1900; - tm.tm_wday = static_cast(extract_weekday(os, fds)); - if (os.fail()) - return os; - tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'X': - if (command) - { - if (modified == CharT{'O'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.has_tod) - os.setstate(std::ios::failbit); -#if !ONLY_C_LOCALE - tm = std::tm{}; - tm.tm_sec = static_cast(fds.tod.seconds().count()); - tm.tm_min = static_cast(fds.tod.minutes().count()); - tm.tm_hour = static_cast(fds.tod.hours().count()); - CharT f[3] = {'%'}; - auto fe = std::begin(f) + 1; - if (modified == CharT{'E'}) - *fe++ = modified; - *fe++ = *fmt; - facet.put(os, os, os.fill(), &tm, std::begin(f), fe); -#else - os << fds.tod; -#endif - } - command = nullptr; - modified = CharT{}; - } - else - os << *fmt; - break; - case 'y': - if (command) - { - if (!fds.ymd.year().ok()) - os.setstate(std::ios::failbit); - auto y = static_cast(fds.ymd.year()); -#if !ONLY_C_LOCALE - if (modified == CharT{}) - { -#endif - y = std::abs(y) % 100; - if (y < 10) - os << CharT{'0'}; - os << y; -#if !ONLY_C_LOCALE - } - else - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_year = y - 1900; - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'Y': - if (command) - { - if (modified == CharT{'O'}) - os << CharT{'%'} << modified << *fmt; - else - { - if (!fds.ymd.year().ok()) - os.setstate(std::ios::failbit); - auto y = fds.ymd.year(); -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - os << y; - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'E'}) - { - const CharT f[] = {'%', modified, *fmt}; - tm.tm_year = static_cast(y) - 1900; - facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); - } -#endif - } - modified = CharT{}; - command = nullptr; - } - else - os << *fmt; - break; - case 'z': - if (command) - { - if (offset_sec == nullptr) - { - // Can not format %z with unknown offset - os.setstate(ios::failbit); - return os; - } - auto m = duration_cast(*offset_sec); - auto neg = m < minutes{0}; - m = date::abs(m); - auto h = duration_cast(m); - m -= h; - if (neg) - os << CharT{'-'}; - else - os << CharT{'+'}; - if (h < hours{10}) - os << CharT{'0'}; - os << h.count(); - if (modified != CharT{}) - os << CharT{':'}; - if (m < minutes{10}) - os << CharT{'0'}; - os << m.count(); - command = nullptr; - modified = CharT{}; - } - else - os << *fmt; - break; - case 'Z': - if (command) - { - if (modified == CharT{}) - { - if (abbrev == nullptr) - { - // Can not format %Z with unknown time_zone - os.setstate(ios::failbit); - return os; - } - for (auto c : *abbrev) - os << CharT(c); - } - else - { - os << CharT{'%'} << modified << *fmt; - modified = CharT{}; - } - command = nullptr; - } - else - os << *fmt; - break; - case 'E': - case 'O': - if (command) - { - if (modified == CharT{}) - { - modified = *fmt; - } - else - { - os << CharT{'%'} << modified << *fmt; - command = nullptr; - modified = CharT{}; - } - } - else - os << *fmt; - break; - case '%': - if (command) - { - if (modified == CharT{}) - { - os << CharT{'%'}; - command = nullptr; - } - else - { - os << CharT{'%'} << modified << CharT{'%'}; - command = nullptr; - modified = CharT{}; - } - } - else - command = fmt; - break; - default: - if (command) - { - os << CharT{'%'}; - command = nullptr; - } - if (modified != CharT{}) - { - os << modified; - modified = CharT{}; - } - os << *fmt; - break; } - } - if (command) + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'b': + case 'B': + case 'h': + if (command) { + if (modified == CharT{}) { + tm.tm_mon = static_cast(extract_month(os, fds)) - 1; +#if !ONLY_C_LOCALE + const CharT f[] = {'%', *fmt}; + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); +#else // ONLY_C_LOCALE + os << month_names().first[tm.tm_mon + 12 * (*fmt != 'B')]; +#endif // ONLY_C_LOCALE + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'c': + case 'x': + if (command) { + if (modified == CharT{'O'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.ymd.ok()) { + os.setstate(std::ios::failbit); + } + if (*fmt == 'c' && !fds.has_tod) { + os.setstate(std::ios::failbit); + } +#if !ONLY_C_LOCALE + tm = std::tm {}; + auto const &ymd = fds.ymd; + auto ld = local_days(ymd); + if (*fmt == 'c') { + tm.tm_sec = static_cast(fds.tod.seconds().count()); + tm.tm_min = static_cast(fds.tod.minutes().count()); + tm.tm_hour = static_cast(fds.tod.hours().count()); + } + tm.tm_mday = static_cast(static_cast(ymd.day())); + tm.tm_mon = static_cast(extract_month(os, fds) - 1); + tm.tm_year = static_cast(ymd.year()) - 1900; + tm.tm_wday = static_cast(extract_weekday(os, fds)); + if (os.fail()) { + return os; + } + tm.tm_yday = static_cast((ld - local_days(ymd.year() / 1 / 1)).count()); + CharT f[3] = {'%'}; + auto fe = std::begin(f) + 1; + if (modified == CharT{'E'}) + *fe++ = modified; + *fe++ = *fmt; + facet.put(os, os, os.fill(), &tm, std::begin(f), fe); +#else // ONLY_C_LOCALE + if (*fmt == 'c') { + auto wd = static_cast(extract_weekday(os, fds)); + os << weekday_names().first[static_cast(wd) + 7] + << ' '; + os << month_names().first[extract_month(os, fds) - 1 + 12] << ' '; + auto d = static_cast(static_cast(fds.ymd.day())); + if (d < 10) { + os << ' '; + } + os << d << ' ' + << make_time(duration_cast(fds.tod.to_duration())) + << ' ' << fds.ymd.year(); + + } + else { // *fmt == 'x' + auto const &ymd = fds.ymd; + save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(2); + os << static_cast(ymd.month()) << CharT{'/'}; + os.width(2); + os << static_cast(ymd.day()) << CharT{'/'}; + os.width(2); + os << static_cast(ymd.year()) % 100; + } +#endif // ONLY_C_LOCALE + } + command = nullptr; + modified = CharT{}; + } + else { + os << *fmt; + } + break; + case 'C': + if (command) { + if (modified == CharT{'O'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.ymd.year().ok()) { + os.setstate(std::ios::failbit); + } + auto y = static_cast(fds.ymd.year()); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + if (y >= 0) { + os.width(2); + os << y / 100; + } + else { + os << CharT{'-'}; + os.width(2); + os << -(y - 99) / 100; + } + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'E'}) { + tm.tm_year = y - 1900; + CharT f[3] = {'%', 'E', 'C'}; + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + command = nullptr; + modified = CharT{}; + } + else { + os << *fmt; + } + break; + case 'd': + case 'e': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.ymd.day().ok()) { + os.setstate(std::ios::failbit); + } + auto d = static_cast(static_cast(fds.ymd.day())); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + save_ostream _(os); + if (*fmt == CharT{'d'}) + os.fill('0'); + else { + os.fill(' '); + } + os.flags(std::ios::dec | std::ios::right); + os.width(2); + os << d; + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + tm.tm_mday = d; + CharT f[3] = {'%', 'O', *fmt}; + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + command = nullptr; + modified = CharT{}; + } + else { + os << *fmt; + } + break; + case 'D': + if (command) { + if (modified == CharT{}) { + if (!fds.ymd.ok()) { + os.setstate(std::ios::failbit); + } + auto const &ymd = fds.ymd; + save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(2); + os << static_cast(ymd.month()) << CharT{'/'}; + os.width(2); + os << static_cast(ymd.day()) << CharT{'/'}; + os.width(2); + os << static_cast(ymd.year()) % 100; + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'F': + if (command) { + if (modified == CharT{}) { + if (!fds.ymd.ok()) { + os.setstate(std::ios::failbit); + } + auto const &ymd = fds.ymd; + save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(4); + os << static_cast(ymd.year()) << CharT{'-'}; + os.width(2); + os << static_cast(ymd.month()) << CharT{'-'}; + os.width(2); + os << static_cast(ymd.day()); + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'g': + case 'G': + if (command) { + if (modified == CharT{}) { + if (!fds.ymd.ok()) { + os.setstate(std::ios::failbit); + } + auto ld = local_days(fds.ymd); + auto y = year_month_day{ld + days{3}}.year(); + auto start = local_days((y - years{1}) / December / Thursday[last]) + + (Monday - Thursday); + if (ld < start) { + --y; + } + if (*fmt == CharT{'G'}) + os << y; + else { + save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(2); + os << std::abs(static_cast(y)) % 100; + } + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'H': + case 'I': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } + if (insert_negative) { + os << '-'; + insert_negative = false; + } + auto hms = fds.tod; +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + auto h = *fmt == CharT{'I'} ? make12(hms.hours()) : hms.hours(); + if (h < hours{10}) + os << CharT{'0'}; + os << h.count(); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_hour = static_cast(hms.hours().count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'j': + if (command) { + if (modified == CharT{}) { + if (fds.ymd.ok() || fds.has_tod) { + days doy; + if (fds.ymd.ok()) { + auto ld = local_days(fds.ymd); + auto y = fds.ymd.year(); + doy = ld - local_days(y / January / 1) + days{1}; + } + else { + doy = duration_cast(fds.tod.to_duration()); + } + save_ostream _(os); + os.fill('0'); + os.flags(std::ios::dec | std::ios::right); + os.width(3); + os << doy.count(); + } + else { + os.setstate(std::ios::failbit); + } + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'm': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.ymd.month().ok()) { + os.setstate(std::ios::failbit); + } + auto m = static_cast(fds.ymd.month()); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + if (m < 10) + os << CharT{'0'}; + os << m; + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_mon = static_cast(m - 1); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'M': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } + if (insert_negative) { + os << '-'; + insert_negative = false; + } +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + if (fds.tod.minutes() < minutes{10}) + os << CharT{'0'}; + os << fds.tod.minutes().count(); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_min = static_cast(fds.tod.minutes().count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'n': + if (command) { + if (modified == CharT{}) + os << CharT{'\n'}; + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'p': + if (command) { + if (modified == CharT{}) { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } +#if !ONLY_C_LOCALE + const CharT f[] = {'%', *fmt}; + tm.tm_hour = static_cast(fds.tod.hours().count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); +#else + if (is_am(fds.tod.hours())) { + os << ampm_names().first[0]; + } + else { + os << ampm_names().first[1]; + } +#endif + } + else { + os << CharT{'%'} << modified << *fmt; + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'Q': + case 'q': + if (command) { + if (modified == CharT{}) { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } + auto d = fds.tod.to_duration(); + if (*fmt == 'q') + os << get_units(typename decltype(d)::period::type{}); + else { + os << d.count(); + } + } + else { + os << CharT{'%'} << modified << *fmt; + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'r': + if (command) { + if (modified == CharT{}) { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } +#if !ONLY_C_LOCALE + const CharT f[] = {'%', *fmt}; + tm.tm_hour = static_cast(fds.tod.hours().count()); + tm.tm_min = static_cast(fds.tod.minutes().count()); + tm.tm_sec = static_cast(fds.tod.seconds().count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); +#else + hh_mm_ss tod(duration_cast(fds.tod.to_duration())); + save_ostream _(os); + os.fill('0'); + os.width(2); + os << make12(tod.hours()).count() << CharT{':'}; + os.width(2); + os << tod.minutes().count() << CharT{':'}; + os.width(2); + os << tod.seconds().count() << CharT{' '}; + if (is_am(tod.hours())) { + os << ampm_names().first[0]; + } + else { + os << ampm_names().first[1]; + } +#endif + } + else { + os << CharT{'%'} << modified << *fmt; + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'R': + if (command) { + if (modified == CharT{}) { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } + if (fds.tod.hours() < hours{10}) + os << CharT{'0'}; + os << fds.tod.hours().count() << CharT{':'}; + if (fds.tod.minutes() < minutes{10}) + os << CharT{'0'}; + os << fds.tod.minutes().count(); + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'S': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } + if (insert_negative) { + os << '-'; + insert_negative = false; + } +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + os << fds.tod.s_; + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_sec = static_cast(fds.tod.s_.seconds().count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 't': + if (command) { + if (modified == CharT{}) + os << CharT{'\t'}; + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'T': + if (command) { + if (modified == CharT{}) { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } + os << fds.tod; + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'u': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + auto wd = extract_weekday(os, fds); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + os << (wd != 0 ? wd : 7u); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_wday = static_cast(wd); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'U': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + auto const &ymd = fds.ymd; + if (!ymd.ok()) { + os.setstate(std::ios::failbit); + } + auto ld = local_days(ymd); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + auto st = local_days(Sunday[1] / January / ymd.year()); + if (ld < st) + os << CharT{'0'} << CharT{'0'}; + else { + auto wn = duration_cast(ld - st).count() + 1; + if (wn < 10) + os << CharT{'0'}; + os << wn; + } + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_year = static_cast(ymd.year()) - 1900; + tm.tm_wday = static_cast(extract_weekday(os, fds)); + if (os.fail()) { + return os; + } + tm.tm_yday = static_cast((ld - local_days(ymd.year() / 1 / 1)).count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'V': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.ymd.ok()) { + os.setstate(std::ios::failbit); + } + auto ld = local_days(fds.ymd); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + auto y = year_month_day{ld + days{3}}.year(); + auto st = local_days((y - years{1}) / 12 / Thursday[last]) + + (Monday - Thursday); + if (ld < st) { + --y; + st = local_days((y - years{1}) / 12 / Thursday[last]) + + (Monday - Thursday); + } + auto wn = duration_cast(ld - st).count() + 1; + if (wn < 10) + os << CharT{'0'}; + os << wn; + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + auto const &ymd = fds.ymd; + tm.tm_year = static_cast(ymd.year()) - 1900; + tm.tm_wday = static_cast(extract_weekday(os, fds)); + if (os.fail()) { + return os; + } + tm.tm_yday = static_cast((ld - local_days(ymd.year() / 1 / 1)).count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'w': + if (command) { + auto wd = extract_weekday(os, fds); + if (os.fail()) { + return os; + } +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + os << wd; + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_wday = static_cast(wd); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + else { + os << CharT{'%'} << modified << *fmt; + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'W': + if (command) { + if (modified == CharT{'E'}) + os << CharT{'%'} << modified << *fmt; + else { + auto const &ymd = fds.ymd; + if (!ymd.ok()) { + os.setstate(std::ios::failbit); + } + auto ld = local_days(ymd); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + auto st = local_days(Monday[1] / January / ymd.year()); + if (ld < st) + os << CharT{'0'} << CharT{'0'}; + else { + auto wn = duration_cast(ld - st).count() + 1; + if (wn < 10) + os << CharT{'0'}; + os << wn; + } + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_year = static_cast(ymd.year()) - 1900; + tm.tm_wday = static_cast(extract_weekday(os, fds)); + if (os.fail()) { + return os; + } + tm.tm_yday = static_cast((ld - local_days(ymd.year() / 1 / 1)).count()); + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'X': + if (command) { + if (modified == CharT{'O'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.has_tod) { + os.setstate(std::ios::failbit); + } +#if !ONLY_C_LOCALE + tm = std::tm {}; + tm.tm_sec = static_cast(fds.tod.seconds().count()); + tm.tm_min = static_cast(fds.tod.minutes().count()); + tm.tm_hour = static_cast(fds.tod.hours().count()); + CharT f[3] = {'%'}; + auto fe = std::begin(f) + 1; + if (modified == CharT{'E'}) + *fe++ = modified; + *fe++ = *fmt; + facet.put(os, os, os.fill(), &tm, std::begin(f), fe); +#else + os << fds.tod; +#endif + } + command = nullptr; + modified = CharT{}; + } + else { + os << *fmt; + } + break; + case 'y': + if (command) { + if (!fds.ymd.year().ok()) { + os.setstate(std::ios::failbit); + } + auto y = static_cast(fds.ymd.year()); +#if !ONLY_C_LOCALE + if (modified == CharT {}) { +#endif + y = std::abs(y) % 100; + if (y < 10) + os << CharT{'0'}; + os << y; +#if !ONLY_C_LOCALE + } + else { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_year = y - 1900; + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + modified = CharT {}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'Y': + if (command) { + if (modified == CharT{'O'}) + os << CharT{'%'} << modified << *fmt; + else { + if (!fds.ymd.year().ok()) { + os.setstate(std::ios::failbit); + } + auto y = fds.ymd.year(); +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + os << y; + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'E'}) { + const CharT f[] = {'%', modified, *fmt}; + tm.tm_year = static_cast(y) - 1900; + facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); + } +#endif + } + modified = CharT{}; + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'z': + if (command) { + if (offset_sec == nullptr) { + // Can not format %z with unknown offset + os.setstate(ios::failbit); + return os; + } + auto m = duration_cast(*offset_sec); + auto neg = m < minutes{0}; + m = date::abs(m); + auto h = duration_cast(m); + m -= h; + if (neg) + os << CharT{'-'}; + else + os << CharT{'+'}; + if (h < hours{10}) + os << CharT{'0'}; + os << h.count(); + if (modified != CharT{}) + os << CharT{':'}; + if (m < minutes{10}) + os << CharT{'0'}; + os << m.count(); + command = nullptr; + modified = CharT{}; + } + else { + os << *fmt; + } + break; + case 'Z': + if (command) { + if (modified == CharT{}) { + if (abbrev == nullptr) { + // Can not format %Z with unknown time_zone + os.setstate(ios::failbit); + return os; + } + for (auto c : *abbrev) { + os << CharT(c); + } + } + else { + os << CharT{'%'} << modified << *fmt; + modified = CharT{}; + } + command = nullptr; + } + else { + os << *fmt; + } + break; + case 'E': + case 'O': + if (command) { + if (modified == CharT{}) { + modified = *fmt; + } + else { + os << CharT{'%'} << modified << *fmt; + command = nullptr; + modified = CharT{}; + } + } + else { + os << *fmt; + } + break; + case '%': + if (command) { + if (modified == CharT{}) { + os << CharT{'%'}; + command = nullptr; + } + else { + os << CharT{'%'} << modified << CharT{'%'}; + command = nullptr; + modified = CharT{}; + } + } + else { + command = fmt; + } + break; + default: + if (command) { os << CharT{'%'}; - if (modified != CharT{}) + command = nullptr; + } + if (modified != CharT{}) { os << modified; - return os; + modified = CharT{}; + } + os << *fmt; + break; + } + } + if (command) + os << CharT{'%'}; + if (modified != CharT{}) + os << modified; + return os; } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, const year& y) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, const year &y) { - using CT = std::chrono::seconds; - fields fds{y/0/0}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{y / 0 / 0}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, const month& m) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, const month &m) { - using CT = std::chrono::seconds; - fields fds{m/0/nanyear}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{m / 0 / nanyear}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, const day& d) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, const day &d) { - using CT = std::chrono::seconds; - fields fds{d/0/nanyear}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{d / 0 / nanyear}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, const weekday& wd) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, const weekday &wd) { - using CT = std::chrono::seconds; - fields fds{wd}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{wd}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, const year_month& ym) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, const year_month &ym) { - using CT = std::chrono::seconds; - fields fds{ym/0}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{ym / 0}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, const month_day& md) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, const month_day &md) { - using CT = std::chrono::seconds; - fields fds{md/nanyear}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{md / nanyear}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, - const year_month_day& ymd) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, + const year_month_day &ymd) { - using CT = std::chrono::seconds; - fields fds{ymd}; - return to_stream(os, fmt, fds); + using CT = std::chrono::seconds; + fields fds{ymd}; + return to_stream(os, fmt, fds); } template inline -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, - const std::chrono::duration& d) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, + const std::chrono::duration &d) { - using Duration = std::chrono::duration; - using CT = typename std::common_type::type; - fields fds{hh_mm_ss{d}}; - return to_stream(os, fmt, fds); + using Duration = std::chrono::duration; + using CT = typename std::common_type::type; + fields fds{hh_mm_ss{d}}; + return to_stream(os, fmt, fds); } template -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, - const local_time& tp, const std::string* abbrev = nullptr, - const std::chrono::seconds* offset_sec = nullptr) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, + const local_time &tp, const std::string *abbrev = nullptr, + const std::chrono::seconds *offset_sec = nullptr) { - using CT = typename std::common_type::type; - auto ld = floor(tp); - fields fds{year_month_day{ld}, hh_mm_ss{tp-local_seconds{ld}}}; - return to_stream(os, fmt, fds, abbrev, offset_sec); + using CT = typename std::common_type::type; + auto ld = floor(tp); + fields fds{year_month_day{ld}, hh_mm_ss{tp - local_seconds{ld}}}; + return to_stream(os, fmt, fds, abbrev, offset_sec); } template -std::basic_ostream& -to_stream(std::basic_ostream& os, const CharT* fmt, - const sys_time& tp) +std::basic_ostream & +to_stream(std::basic_ostream &os, const CharT *fmt, + const sys_time &tp) { - using std::chrono::seconds; - using CT = typename std::common_type::type; - const std::string abbrev("UTC"); - CONSTDATA seconds offset{0}; - auto sd = floor(tp); - fields fds{year_month_day{sd}, hh_mm_ss{tp-sys_seconds{sd}}}; - return to_stream(os, fmt, fds, &abbrev, &offset); + using std::chrono::seconds; + using CT = typename std::common_type::type; + const std::string abbrev("UTC"); + CONSTDATA seconds offset{0}; + auto sd = floor(tp); + fields fds{year_month_day{sd}, hh_mm_ss{tp - sys_seconds{sd}}}; + return to_stream(os, fmt, fds, &abbrev, &offset); } // format template auto -format(const std::locale& loc, const CharT* fmt, const Streamable& tp) - -> decltype(to_stream(std::declval&>(), fmt, tp), - std::basic_string{}) +format(const std::locale &loc, const CharT *fmt, const Streamable &tp) +-> decltype(to_stream(std::declval&>(), fmt, tp), +std::basic_string {}) { - std::basic_ostringstream os; - os.exceptions(std::ios::failbit | std::ios::badbit); - os.imbue(loc); - to_stream(os, fmt, tp); - return os.str(); + std::basic_ostringstream os; + os.exceptions(std::ios::failbit | std::ios::badbit); + os.imbue(loc); + to_stream(os, fmt, tp); + return os.str(); } template auto -format(const CharT* fmt, const Streamable& tp) - -> decltype(to_stream(std::declval&>(), fmt, tp), - std::basic_string{}) +format(const CharT *fmt, const Streamable &tp) +-> decltype(to_stream(std::declval&>(), fmt, tp), +std::basic_string {}) { - std::basic_ostringstream os; - os.exceptions(std::ios::failbit | std::ios::badbit); - to_stream(os, fmt, tp); - return os.str(); + std::basic_ostringstream os; + os.exceptions(std::ios::failbit | std::ios::badbit); + to_stream(os, fmt, tp); + return os.str(); } template auto -format(const std::locale& loc, const std::basic_string& fmt, - const Streamable& tp) - -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), - std::basic_string{}) +format(const std::locale &loc, const std::basic_string &fmt, + const Streamable &tp) +-> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), +std::basic_string {}) { - std::basic_ostringstream os; - os.exceptions(std::ios::failbit | std::ios::badbit); - os.imbue(loc); - to_stream(os, fmt.c_str(), tp); - return os.str(); + std::basic_ostringstream os; + os.exceptions(std::ios::failbit | std::ios::badbit); + os.imbue(loc); + to_stream(os, fmt.c_str(), tp); + return os.str(); } template auto -format(const std::basic_string& fmt, const Streamable& tp) - -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), - std::basic_string{}) +format(const std::basic_string &fmt, const Streamable &tp) +-> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), +std::basic_string {}) { - std::basic_ostringstream os; - os.exceptions(std::ios::failbit | std::ios::badbit); - to_stream(os, fmt.c_str(), tp); - return os.str(); + std::basic_ostringstream os; + os.exceptions(std::ios::failbit | std::ios::badbit); + to_stream(os, fmt.c_str(), tp); + return os.str(); } // parse -namespace detail -{ +namespace detail { template bool -read_char(std::basic_istream& is, CharT fmt, std::ios::iostate& err) +read_char(std::basic_istream &is, CharT fmt, std::ios::iostate &err) { - auto ic = is.get(); - if (Traits::eq_int_type(ic, Traits::eof()) || - !Traits::eq(Traits::to_char_type(ic), fmt)) - { - err |= std::ios::failbit; - is.setstate(std::ios::failbit); - return false; - } - return true; + auto ic = is.get(); + if (Traits::eq_int_type(ic, Traits::eof()) || + !Traits::eq(Traits::to_char_type(ic), fmt)) { + err |= std::ios::failbit; + is.setstate(std::ios::failbit); + return false; + } + return true; } template unsigned -read_unsigned(std::basic_istream& is, unsigned m = 1, unsigned M = 10) +read_unsigned(std::basic_istream &is, unsigned m = 1, unsigned M = 10) { - unsigned x = 0; - unsigned count = 0; - while (true) - { - auto ic = is.peek(); - if (Traits::eq_int_type(ic, Traits::eof())) - break; - auto c = static_cast(Traits::to_char_type(ic)); - if (!('0' <= c && c <= '9')) - break; - (void)is.get(); - ++count; - x = 10*x + static_cast(c - '0'); - if (count == M) - break; + unsigned x = 0; + unsigned count = 0; + while (true) { + auto ic = is.peek(); + if (Traits::eq_int_type(ic, Traits::eof())) { + break; } - if (count < m) - is.setstate(std::ios::failbit); - return x; + auto c = static_cast(Traits::to_char_type(ic)); + if (!('0' <= c && c <= '9')) { + break; + } + (void)is.get(); + ++count; + x = 10 * x + static_cast(c - '0'); + if (count == M) { + break; + } + } + if (count < m) { + is.setstate(std::ios::failbit); + } + return x; } template int -read_signed(std::basic_istream& is, unsigned m = 1, unsigned M = 10) +read_signed(std::basic_istream &is, unsigned m = 1, unsigned M = 10) { - auto ic = is.peek(); - if (!Traits::eq_int_type(ic, Traits::eof())) - { - auto c = static_cast(Traits::to_char_type(ic)); - if (('0' <= c && c <= '9') || c == '-' || c == '+') - { - if (c == '-' || c == '+') - (void)is.get(); - auto x = static_cast(read_unsigned(is, std::max(m, 1u), M)); - if (!is.fail()) - { - if (c == '-') - x = -x; - return x; - } + auto ic = is.peek(); + if (!Traits::eq_int_type(ic, Traits::eof())) { + auto c = static_cast(Traits::to_char_type(ic)); + if (('0' <= c && c <= '9') || c == '-' || c == '+') { + if (c == '-' || c == '+') { + (void)is.get(); + } + auto x = static_cast(read_unsigned(is, std::max(m, 1u), M)); + if (!is.fail()) { + if (c == '-') { + x = -x; } + return x; + } } - if (m > 0) - is.setstate(std::ios::failbit); - return 0; + } + if (m > 0) { + is.setstate(std::ios::failbit); + } + return 0; } template long double -read_long_double(std::basic_istream& is, unsigned m = 1, unsigned M = 10) +read_long_double(std::basic_istream &is, unsigned m = 1, unsigned M = 10) { - unsigned count = 0; - auto decimal_point = Traits::to_int_type( - std::use_facet>(is.getloc()).decimal_point()); - std::string buf; - while (true) - { - auto ic = is.peek(); - if (Traits::eq_int_type(ic, Traits::eof())) - break; - if (Traits::eq_int_type(ic, decimal_point)) - { - buf += '.'; - decimal_point = Traits::eof(); - is.get(); - } - else - { - auto c = static_cast(Traits::to_char_type(ic)); - if (!('0' <= c && c <= '9')) - break; - buf += c; - (void)is.get(); - } - if (++count == M) - break; + unsigned count = 0; + auto decimal_point = Traits::to_int_type( + std::use_facet>(is.getloc()).decimal_point()); + std::string buf; + while (true) { + auto ic = is.peek(); + if (Traits::eq_int_type(ic, Traits::eof())) { + break; } - if (count < m) - { - is.setstate(std::ios::failbit); - return 0; + if (Traits::eq_int_type(ic, decimal_point)) { + buf += '.'; + decimal_point = Traits::eof(); + is.get(); } - return std::stold(buf); + else { + auto c = static_cast(Traits::to_char_type(ic)); + if (!('0' <= c && c <= '9')) { + break; + } + buf += c; + (void)is.get(); + } + if (++count == M) { + break; + } + } + if (count < m) { + is.setstate(std::ios::failbit); + return 0; + } + return std::stold(buf); } -struct rs -{ - int& i; - unsigned m; - unsigned M; +struct rs { + int &i; + unsigned m; + unsigned M; }; -struct ru -{ - int& i; - unsigned m; - unsigned M; +struct ru { + int &i; + unsigned m; + unsigned M; }; -struct rld -{ - long double& i; - unsigned m; - unsigned M; +struct rld { + long double &i; + unsigned m; + unsigned M; }; template void -read(std::basic_istream&) +read(std::basic_istream &) { } template void -read(std::basic_istream& is, CharT a0, Args&& ...args); +read(std::basic_istream &is, CharT a0, Args &&...args); template void -read(std::basic_istream& is, rs a0, Args&& ...args); +read(std::basic_istream &is, rs a0, Args &&...args); template void -read(std::basic_istream& is, ru a0, Args&& ...args); +read(std::basic_istream &is, ru a0, Args &&...args); template void -read(std::basic_istream& is, int a0, Args&& ...args); +read(std::basic_istream &is, int a0, Args &&...args); template void -read(std::basic_istream& is, rld a0, Args&& ...args); +read(std::basic_istream &is, rld a0, Args &&...args); template void -read(std::basic_istream& is, CharT a0, Args&& ...args) +read(std::basic_istream &is, CharT a0, Args &&...args) { - // No-op if a0 == CharT{} - if (a0 != CharT{}) - { - auto ic = is.peek(); - if (Traits::eq_int_type(ic, Traits::eof())) - { - is.setstate(std::ios::failbit | std::ios::eofbit); - return; - } - if (!Traits::eq(Traits::to_char_type(ic), a0)) - { - is.setstate(std::ios::failbit); - return; - } - (void)is.get(); + // No-op if a0 == CharT{} + if (a0 != CharT{}) { + auto ic = is.peek(); + if (Traits::eq_int_type(ic, Traits::eof())) { + is.setstate(std::ios::failbit | std::ios::eofbit); + return; } - read(is, std::forward(args)...); -} - -template -void -read(std::basic_istream& is, rs a0, Args&& ...args) -{ - auto x = read_signed(is, a0.m, a0.M); - if (is.fail()) - return; - a0.i = x; - read(is, std::forward(args)...); -} - -template -void -read(std::basic_istream& is, ru a0, Args&& ...args) -{ - auto x = read_unsigned(is, a0.m, a0.M); - if (is.fail()) - return; - a0.i = static_cast(x); - read(is, std::forward(args)...); -} - -template -void -read(std::basic_istream& is, int a0, Args&& ...args) -{ - if (a0 != -1) - { - auto u = static_cast(a0); - CharT buf[std::numeric_limits::digits10+2] = {}; - auto e = buf; - do - { - *e++ = static_cast(CharT(u % 10) + CharT{'0'}); - u /= 10; - } while (u > 0); - std::reverse(buf, e); - for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p) - read(is, *p); + if (!Traits::eq(Traits::to_char_type(ic), a0)) { + is.setstate(std::ios::failbit); + return; } - if (is.rdstate() == std::ios::goodbit) - read(is, std::forward(args)...); + (void)is.get(); + } + read(is, std::forward(args)...); } template void -read(std::basic_istream& is, rld a0, Args&& ...args) +read(std::basic_istream &is, rs a0, Args &&...args) { - auto x = read_long_double(is, a0.m, a0.M); - if (is.fail()) - return; - a0.i = x; + auto x = read_signed(is, a0.m, a0.M); + if (is.fail()) { + return; + } + a0.i = x; + read(is, std::forward(args)...); +} + +template +void +read(std::basic_istream &is, ru a0, Args &&...args) +{ + auto x = read_unsigned(is, a0.m, a0.M); + if (is.fail()) { + return; + } + a0.i = static_cast(x); + read(is, std::forward(args)...); +} + +template +void +read(std::basic_istream &is, int a0, Args &&...args) +{ + if (a0 != -1) { + auto u = static_cast(a0); + CharT buf[std::numeric_limits::digits10 + 2] = {}; + auto e = buf; + do { + *e++ = static_cast(CharT(u % 10) + CharT{'0'}); + u /= 10; + } + while (u > 0); + std::reverse(buf, e); + for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p) { + read(is, *p); + } + } + if (is.rdstate() == std::ios::goodbit) { read(is, std::forward(args)...); + } +} + +template +void +read(std::basic_istream &is, rld a0, Args &&...args) +{ + auto x = read_long_double(is, a0.m, a0.M); + if (is.fail()) { + return; + } + a0.i = x; + read(is, std::forward(args)...); } template inline void -checked_set(T& value, T from, T not_a_value, std::basic_ios& is) +checked_set(T &value, T from, T not_a_value, std::basic_ios &is) { - if (!is.fail()) - { - if (value == not_a_value) - value = std::move(from); - else if (value != from) - is.setstate(std::ios::failbit); + if (!is.fail()) { + if (value == not_a_value) { + value = std::move(from); } + else if (value != from) { + is.setstate(std::ios::failbit); + } + } } } // namespace detail; template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, - fields& fds, std::basic_string* abbrev, - std::chrono::minutes* offset) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, + fields &fds, std::basic_string *abbrev, + std::chrono::minutes *offset) { - using std::numeric_limits; - using std::ios; - using std::chrono::duration; - using std::chrono::duration_cast; - using std::chrono::seconds; - using std::chrono::minutes; - using std::chrono::hours; - typename std::basic_istream::sentry ok{is, true}; - if (ok) - { - date::detail::save_istream ss(is); - is.fill(' '); - is.flags(std::ios::skipws | std::ios::dec); - is.width(0); + using std::numeric_limits; + using std::ios; + using std::chrono::duration; + using std::chrono::duration_cast; + using std::chrono::seconds; + using std::chrono::minutes; + using std::chrono::hours; + typename std::basic_istream::sentry ok{is, true}; + if (ok) { + date::detail::save_istream ss(is); + is.fill(' '); + is.flags(std::ios::skipws | std::ios::dec); + is.width(0); #if !ONLY_C_LOCALE - auto& f = std::use_facet>(is.getloc()); - std::tm tm{}; + auto &f = std::use_facet>(is.getloc()); + std::tm tm{}; #endif - const CharT* command = nullptr; - auto modified = CharT{}; - auto width = -1; + const CharT *command = nullptr; + auto modified = CharT{}; + auto width = -1; - CONSTDATA int not_a_year = numeric_limits::min(); - CONSTDATA int not_a_2digit_year = 100; - CONSTDATA int not_a_century = not_a_year / 100; - CONSTDATA int not_a_month = 0; - CONSTDATA int not_a_day = 0; - CONSTDATA int not_a_hour = numeric_limits::min(); - CONSTDATA int not_a_hour_12_value = 0; - CONSTDATA int not_a_minute = not_a_hour; - CONSTDATA Duration not_a_second = Duration::min(); - CONSTDATA int not_a_doy = -1; - CONSTDATA int not_a_weekday = 8; - CONSTDATA int not_a_week_num = 100; - CONSTDATA int not_a_ampm = -1; - CONSTDATA minutes not_a_offset = minutes::min(); + CONSTDATA int not_a_year = numeric_limits::min(); + CONSTDATA int not_a_2digit_year = 100; + CONSTDATA int not_a_century = not_a_year / 100; + CONSTDATA int not_a_month = 0; + CONSTDATA int not_a_day = 0; + CONSTDATA int not_a_hour = numeric_limits::min(); + CONSTDATA int not_a_hour_12_value = 0; + CONSTDATA int not_a_minute = not_a_hour; + CONSTDATA Duration not_a_second = Duration::min(); + CONSTDATA int not_a_doy = -1; + CONSTDATA int not_a_weekday = 8; + CONSTDATA int not_a_week_num = 100; + CONSTDATA int not_a_ampm = -1; + CONSTDATA minutes not_a_offset = minutes::min(); - int Y = not_a_year; // c, F, Y * - int y = not_a_2digit_year; // D, x, y * - int g = not_a_2digit_year; // g * - int G = not_a_year; // G * - int C = not_a_century; // C * - int m = not_a_month; // b, B, h, m, c, D, F, x * - int d = not_a_day; // c, d, D, e, F, x * - int j = not_a_doy; // j * - int wd = not_a_weekday; // a, A, u, w * - int H = not_a_hour; // c, H, R, T, X * - int I = not_a_hour_12_value; // I, r * - int p = not_a_ampm; // p, r * - int M = not_a_minute; // c, M, r, R, T, X * - Duration s = not_a_second; // c, r, S, T, X * - int U = not_a_week_num; // U * - int V = not_a_week_num; // V * - int W = not_a_week_num; // W * - std::basic_string temp_abbrev; // Z * - minutes temp_offset = not_a_offset; // z * + int Y = not_a_year; // c, F, Y * + int y = not_a_2digit_year; // D, x, y * + int g = not_a_2digit_year; // g * + int G = not_a_year; // G * + int C = not_a_century; // C * + int m = not_a_month; // b, B, h, m, c, D, F, x * + int d = not_a_day; // c, d, D, e, F, x * + int j = not_a_doy; // j * + int wd = not_a_weekday; // a, A, u, w * + int H = not_a_hour; // c, H, R, T, X * + int I = not_a_hour_12_value; // I, r * + int p = not_a_ampm; // p, r * + int M = not_a_minute; // c, M, r, R, T, X * + Duration s = not_a_second; // c, r, S, T, X * + int U = not_a_week_num; // U * + int V = not_a_week_num; // V * + int W = not_a_week_num; // W * + std::basic_string temp_abbrev; // Z * + minutes temp_offset = not_a_offset; // z * - using detail::read; - using detail::rs; - using detail::ru; - using detail::rld; - using detail::checked_set; - for (; *fmt != CharT{} && !is.fail(); ++fmt) - { - switch (*fmt) - { - case 'a': - case 'A': - case 'u': - case 'w': // wd: a, A, u, w - if (command) - { - int trial_wd = not_a_weekday; - if (*fmt == 'a' || *fmt == 'A') - { - if (modified == CharT{}) - { + using detail::read; + using detail::rs; + using detail::ru; + using detail::rld; + using detail::checked_set; + for (; *fmt != CharT{} && !is.fail(); ++fmt) { + switch (*fmt) { + case 'a': + case 'A': + case 'u': + case 'w': // wd: a, A, u, w + if (command) { + int trial_wd = not_a_weekday; + if (*fmt == 'a' || *fmt == 'A') { + if (modified == CharT{}) { #if !ONLY_C_LOCALE - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - is.setstate(err); - if (!is.fail()) - trial_wd = tm.tm_wday; + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + is.setstate(err); + if (!is.fail()) { + trial_wd = tm.tm_wday; + } #else - auto nm = detail::weekday_names(); - auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; - if (!is.fail()) - trial_wd = i % 7; + auto nm = detail::weekday_names(); + auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; + if (!is.fail()) { + trial_wd = i % 7; + } #endif - } - else - read(is, CharT{'%'}, width, modified, *fmt); - } - else // *fmt == 'u' || *fmt == 'w' - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - read(is, ru{trial_wd, 1, width == -1 ? - 1u : static_cast(width)}); - if (!is.fail()) - { - if (*fmt == 'u') - { - if (!(1 <= trial_wd && trial_wd <= 7)) - { - trial_wd = not_a_weekday; - is.setstate(ios::failbit); - } - else if (trial_wd == 7) - trial_wd = 0; - } - else // *fmt == 'w' - { - if (!(0 <= trial_wd && trial_wd <= 6)) - { - trial_wd = not_a_weekday; - is.setstate(ios::failbit); - } - } - } - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - is.setstate(err); - if (!is.fail()) - trial_wd = tm.tm_wday; - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - } - if (trial_wd != not_a_weekday) - checked_set(wd, trial_wd, not_a_weekday, is); - } - else // !command - read(is, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - break; - case 'b': - case 'B': - case 'h': - if (command) - { - if (modified == CharT{}) - { - int ttm = not_a_month; -#if !ONLY_C_LOCALE - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - ttm = tm.tm_mon + 1; - is.setstate(err); -#else - auto nm = detail::month_names(); - auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; - if (!is.fail()) - ttm = i % 12 + 1; -#endif - checked_set(m, ttm, not_a_month, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'c': - if (command) - { - if (modified != CharT{'O'}) - { -#if !ONLY_C_LOCALE - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - { - checked_set(Y, tm.tm_year + 1900, not_a_year, is); - checked_set(m, tm.tm_mon + 1, not_a_month, is); - checked_set(d, tm.tm_mday, not_a_day, is); - checked_set(H, tm.tm_hour, not_a_hour, is); - checked_set(M, tm.tm_min, not_a_minute, is); - checked_set(s, duration_cast(seconds{tm.tm_sec}), - not_a_second, is); - } - is.setstate(err); -#else - // "%a %b %e %T %Y" - auto nm = detail::weekday_names(); - auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; - checked_set(wd, static_cast(i % 7), not_a_weekday, is); - ws(is); - nm = detail::month_names(); - i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; - checked_set(m, static_cast(i % 12 + 1), not_a_month, is); - ws(is); - int td = not_a_day; - read(is, rs{td, 1, 2}); - checked_set(d, td, not_a_day, is); - ws(is); - using dfs = detail::decimal_format_seconds; - CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; - int tH; - int tM; - long double S; - read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, - CharT{':'}, rld{S, 1, w}); - checked_set(H, tH, not_a_hour, is); - checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), - not_a_second, is); - ws(is); - int tY = not_a_year; - read(is, rs{tY, 1, 4u}); - checked_set(Y, tY, not_a_year, is); -#endif - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'x': - if (command) - { - if (modified != CharT{'O'}) - { -#if !ONLY_C_LOCALE - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - { - checked_set(Y, tm.tm_year + 1900, not_a_year, is); - checked_set(m, tm.tm_mon + 1, not_a_month, is); - checked_set(d, tm.tm_mday, not_a_day, is); - } - is.setstate(err); -#else - // "%m/%d/%y" - int ty = not_a_2digit_year; - int tm = not_a_month; - int td = not_a_day; - read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'}, - rs{ty, 1, 2}); - checked_set(y, ty, not_a_2digit_year, is); - checked_set(m, tm, not_a_month, is); - checked_set(d, td, not_a_day, is); -#endif - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'X': - if (command) - { - if (modified != CharT{'O'}) - { -#if !ONLY_C_LOCALE - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - { - checked_set(H, tm.tm_hour, not_a_hour, is); - checked_set(M, tm.tm_min, not_a_minute, is); - checked_set(s, duration_cast(seconds{tm.tm_sec}), - not_a_second, is); - } - is.setstate(err); -#else - // "%T" - using dfs = detail::decimal_format_seconds; - CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; - int tH = not_a_hour; - int tM = not_a_minute; - long double S; - read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, - CharT{':'}, rld{S, 1, w}); - checked_set(H, tH, not_a_hour, is); - checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), - not_a_second, is); -#endif - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'C': - if (command) - { - int tC = not_a_century; -#if !ONLY_C_LOCALE - if (modified == CharT{}) - { -#endif - read(is, rs{tC, 1, width == -1 ? 2u : static_cast(width)}); -#if !ONLY_C_LOCALE - } - else - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - { - auto tY = tm.tm_year + 1900; - tC = (tY >= 0 ? tY : tY-99) / 100; - } - is.setstate(err); - } -#endif - checked_set(C, tC, not_a_century, is); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'D': - if (command) - { - if (modified == CharT{}) - { - int tn = not_a_month; - int td = not_a_day; - int ty = not_a_2digit_year; - read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, - ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, - rs{ty, 1, 2}); - checked_set(y, ty, not_a_2digit_year, is); - checked_set(m, tn, not_a_month, is); - checked_set(d, td, not_a_day, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'F': - if (command) - { - if (modified == CharT{}) - { - int tY = not_a_year; - int tn = not_a_month; - int td = not_a_day; - read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}, - CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2}); - checked_set(Y, tY, not_a_year, is); - checked_set(m, tn, not_a_month, is); - checked_set(d, td, not_a_day, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'd': - case 'e': - if (command) - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - int td = not_a_day; - read(is, rs{td, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(d, td, not_a_day, is); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - command = nullptr; - width = -1; - modified = CharT{}; - if ((err & ios::failbit) == 0) - checked_set(d, tm.tm_mday, not_a_day, is); - is.setstate(err); - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'H': - if (command) - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - int tH = not_a_hour; - read(is, ru{tH, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(H, tH, not_a_hour, is); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - checked_set(H, tm.tm_hour, not_a_hour, is); - is.setstate(err); - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'I': - if (command) - { - if (modified == CharT{}) - { - int tI = not_a_hour_12_value; - // reads in an hour into I, but most be in [1, 12] - read(is, rs{tI, 1, width == -1 ? 2u : static_cast(width)}); - if (!(1 <= tI && tI <= 12)) - is.setstate(ios::failbit); - checked_set(I, tI, not_a_hour_12_value, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'j': - if (command) - { - if (modified == CharT{}) - { - int tj = not_a_doy; - read(is, ru{tj, 1, width == -1 ? 3u : static_cast(width)}); - checked_set(j, tj, not_a_doy, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'M': - if (command) - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - int tM = not_a_minute; - read(is, ru{tM, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(M, tM, not_a_minute, is); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - checked_set(M, tm.tm_min, not_a_minute, is); - is.setstate(err); - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'm': - if (command) - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - int tn = not_a_month; - read(is, rs{tn, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(m, tn, not_a_month, is); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - checked_set(m, tm.tm_mon + 1, not_a_month, is); - is.setstate(err); - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'n': - case 't': - if (command) - { - if (modified == CharT{}) - { - // %n matches a single white space character - // %t matches 0 or 1 white space characters - auto ic = is.peek(); - if (Traits::eq_int_type(ic, Traits::eof())) - { - ios::iostate err = ios::eofbit; - if (*fmt == 'n') - err |= ios::failbit; - is.setstate(err); - break; - } - if (isspace(ic)) - { - (void)is.get(); - } - else if (*fmt == 'n') - is.setstate(ios::failbit); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'p': - if (command) - { - if (modified == CharT{}) - { - int tp = not_a_ampm; -#if !ONLY_C_LOCALE - tm = std::tm{}; - tm.tm_hour = 1; - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - is.setstate(err); - if (tm.tm_hour == 1) - tp = 0; - else if (tm.tm_hour == 13) - tp = 1; - else - is.setstate(err); -#else - auto nm = detail::ampm_names(); - auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; - tp = i; -#endif - checked_set(p, tp, not_a_ampm, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - - break; - case 'r': - if (command) - { - if (modified == CharT{}) - { -#if !ONLY_C_LOCALE - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - { - checked_set(H, tm.tm_hour, not_a_hour, is); - checked_set(M, tm.tm_min, not_a_hour, is); - checked_set(s, duration_cast(seconds{tm.tm_sec}), - not_a_second, is); - } - is.setstate(err); -#else - // "%I:%M:%S %p" - using dfs = detail::decimal_format_seconds; - CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; - long double S; - int tI = not_a_hour_12_value; - int tM = not_a_minute; - read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2}, - CharT{':'}, rld{S, 1, w}); - checked_set(I, tI, not_a_hour_12_value, is); - checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), - not_a_second, is); - ws(is); - auto nm = detail::ampm_names(); - auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; - checked_set(p, static_cast(i), not_a_ampm, is); -#endif - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'R': - if (command) - { - if (modified == CharT{}) - { - int tH = not_a_hour; - int tM = not_a_minute; - read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'}, - ru{tM, 1, 2}, CharT{'\0'}); - checked_set(H, tH, not_a_hour, is); - checked_set(M, tM, not_a_minute, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'S': - if (command) - { - #if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'E'}) -#endif - { - using dfs = detail::decimal_format_seconds; - CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; - long double S; - read(is, rld{S, 1, width == -1 ? w : static_cast(width)}); - checked_set(s, round(duration{S}), - not_a_second, is); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'O'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - checked_set(s, duration_cast(seconds{tm.tm_sec}), - not_a_second, is); - is.setstate(err); - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'T': - if (command) - { - if (modified == CharT{}) - { - using dfs = detail::decimal_format_seconds; - CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; - int tH = not_a_hour; - int tM = not_a_minute; - long double S; - read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, - CharT{':'}, rld{S, 1, w}); - checked_set(H, tH, not_a_hour, is); - checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), - not_a_second, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'Y': - if (command) - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#else - if (modified != CharT{'O'}) -#endif - { - int tY = not_a_year; - read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}); - checked_set(Y, tY, not_a_year, is); - } -#if !ONLY_C_LOCALE - else if (modified == CharT{'E'}) - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - checked_set(Y, tm.tm_year + 1900, not_a_year, is); - is.setstate(err); - } -#endif - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'y': - if (command) - { -#if !ONLY_C_LOCALE - if (modified == CharT{}) -#endif - { - int ty = not_a_2digit_year; - read(is, ru{ty, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(y, ty, not_a_2digit_year, is); - } -#if !ONLY_C_LOCALE - else - { - ios::iostate err = ios::goodbit; - f.get(is, nullptr, is, err, &tm, command, fmt+1); - if ((err & ios::failbit) == 0) - checked_set(Y, tm.tm_year + 1900, not_a_year, is); - is.setstate(err); - } -#endif - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'g': - if (command) - { - if (modified == CharT{}) - { - int tg = not_a_2digit_year; - read(is, ru{tg, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(g, tg, not_a_2digit_year, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'G': - if (command) - { - if (modified == CharT{}) - { - int tG = not_a_year; - read(is, rs{tG, 1, width == -1 ? 4u : static_cast(width)}); - checked_set(G, tG, not_a_year, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'U': - if (command) - { - if (modified == CharT{}) - { - int tU = not_a_week_num; - read(is, ru{tU, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(U, tU, not_a_week_num, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'V': - if (command) - { - if (modified == CharT{}) - { - int tV = not_a_week_num; - read(is, ru{tV, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(V, tV, not_a_week_num, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'W': - if (command) - { - if (modified == CharT{}) - { - int tW = not_a_week_num; - read(is, ru{tW, 1, width == -1 ? 2u : static_cast(width)}); - checked_set(W, tW, not_a_week_num, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'E': - case 'O': - if (command) - { - if (modified == CharT{}) - { - modified = *fmt; - } - else - { - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - } - else - read(is, *fmt); - break; - case '%': - if (command) - { - if (modified == CharT{}) - read(is, *fmt); - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - command = fmt; - break; - case 'z': - if (command) - { - int tH, tM; - minutes toff = not_a_offset; - bool neg = false; - auto ic = is.peek(); - if (!Traits::eq_int_type(ic, Traits::eof())) - { - auto c = static_cast(Traits::to_char_type(ic)); - if (c == '-') - neg = true; - } - if (modified == CharT{}) - { - read(is, rs{tH, 2, 2}); - if (!is.fail()) - toff = hours{std::abs(tH)}; - if (is.good()) - { - ic = is.peek(); - if (!Traits::eq_int_type(ic, Traits::eof())) - { - auto c = static_cast(Traits::to_char_type(ic)); - if ('0' <= c && c <= '9') - { - read(is, ru{tM, 2, 2}); - if (!is.fail()) - toff += minutes{tM}; - } - } - } - } - else - { - read(is, rs{tH, 1, 2}); - if (!is.fail()) - toff = hours{std::abs(tH)}; - if (is.good()) - { - ic = is.peek(); - if (!Traits::eq_int_type(ic, Traits::eof())) - { - auto c = static_cast(Traits::to_char_type(ic)); - if (c == ':') - { - (void)is.get(); - read(is, ru{tM, 2, 2}); - if (!is.fail()) - toff += minutes{tM}; - } - } - } - } - if (neg) - toff = -toff; - checked_set(temp_offset, toff, not_a_offset, is); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - case 'Z': - if (command) - { - if (modified == CharT{}) - { - std::basic_string buf; - while (is.rdstate() == std::ios::goodbit) - { - auto i = is.rdbuf()->sgetc(); - if (Traits::eq_int_type(i, Traits::eof())) - { - is.setstate(ios::eofbit); - break; - } - auto wc = Traits::to_char_type(i); - auto c = static_cast(wc); - // is c a valid time zone name or abbreviation character? - if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) || - c == '_' || c == '/' || c == '-' || c == '+')) - break; - buf.push_back(c); - is.rdbuf()->sbumpc(); - } - if (buf.empty()) - is.setstate(ios::failbit); - checked_set(temp_abbrev, buf, {}, is); - } - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - else - read(is, *fmt); - break; - default: - if (command) - { - if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9') - { - width = static_cast(*fmt) - '0'; - while ('0' <= fmt[1] && fmt[1] <= '9') - width = 10*width + static_cast(*++fmt) - '0'; - } - else - { - if (modified == CharT{}) - read(is, CharT{'%'}, width, *fmt); - else - read(is, CharT{'%'}, width, modified, *fmt); - command = nullptr; - width = -1; - modified = CharT{}; - } - } - else // !command - { - if (isspace(static_cast(*fmt))) - { - // space matches 0 or more white space characters - if (is.good()) - ws(is); - } - else - read(is, *fmt); - } - break; } - } - // is.fail() || *fmt == CharT{} - if (is.rdstate() == ios::goodbit && command) - { - if (modified == CharT{}) - read(is, CharT{'%'}, width); else - read(is, CharT{'%'}, width, modified); + read(is, CharT{'%'}, width, modified, *fmt); + } + else { // *fmt == 'u' || *fmt == 'w' +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + read(is, ru{trial_wd, 1, width == -1 ? + 1u : static_cast(width)}); + if (!is.fail()) { + if (*fmt == 'u') { + if (!(1 <= trial_wd && trial_wd <= 7)) { + trial_wd = not_a_weekday; + is.setstate(ios::failbit); + } + else if (trial_wd == 7) { + trial_wd = 0; + } + } + else { // *fmt == 'w' + if (!(0 <= trial_wd && trial_wd <= 6)) { + trial_wd = not_a_weekday; + is.setstate(ios::failbit); + } + } + } + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + is.setstate(err); + if (!is.fail()) { + trial_wd = tm.tm_wday; + } + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + } + if (trial_wd != not_a_weekday) { + checked_set(wd, trial_wd, not_a_weekday, is); + } } - if (!is.fail()) - { - if (y != not_a_2digit_year) - { - // Convert y and an optional C to Y - if (!(0 <= y && y <= 99)) - goto broken; - if (C == not_a_century) - { - if (Y == not_a_year) - { - if (y >= 69) - C = 19; - else - C = 20; - } - else - { - C = (Y >= 0 ? Y : Y-100) / 100; - } - } - int tY; - if (C >= 0) - tY = 100*C + y; - else - tY = 100*(C+1) - (y == 0 ? 100 : y); - if (Y != not_a_year && Y != tY) - goto broken; - Y = tY; - } - if (g != not_a_2digit_year) - { - // Convert g and an optional C to G - if (!(0 <= g && g <= 99)) - goto broken; - if (C == not_a_century) - { - if (G == not_a_year) - { - if (g >= 69) - C = 19; - else - C = 20; - } - else - { - C = (G >= 0 ? G : G-100) / 100; - } - } - int tG; - if (C >= 0) - tG = 100*C + g; - else - tG = 100*(C+1) - (g == 0 ? 100 : g); - if (G != not_a_year && G != tG) - goto broken; - G = tG; - } - if (Y < static_cast(year::min()) || Y > static_cast(year::max())) - Y = not_a_year; - bool computed = false; - if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday) - { - year_month_day ymd_trial = sys_days(year{G-1}/December/Thursday[last]) + - (Monday-Thursday) + weeks{V-1} + - (weekday{static_cast(wd)}-Monday); - if (Y == not_a_year) - Y = static_cast(ymd_trial.year()); - else if (year{Y} != ymd_trial.year()) - goto broken; - if (m == not_a_month) - m = static_cast(static_cast(ymd_trial.month())); - else if (month(static_cast(m)) != ymd_trial.month()) - goto broken; - if (d == not_a_day) - d = static_cast(static_cast(ymd_trial.day())); - else if (day(static_cast(d)) != ymd_trial.day()) - goto broken; - computed = true; - } - if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday) - { - year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) + - weeks{U-1} + - (weekday{static_cast(wd)} - Sunday); - if (Y == not_a_year) - Y = static_cast(ymd_trial.year()); - else if (year{Y} != ymd_trial.year()) - goto broken; - if (m == not_a_month) - m = static_cast(static_cast(ymd_trial.month())); - else if (month(static_cast(m)) != ymd_trial.month()) - goto broken; - if (d == not_a_day) - d = static_cast(static_cast(ymd_trial.day())); - else if (day(static_cast(d)) != ymd_trial.day()) - goto broken; - computed = true; - } - if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday) - { - year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) + - weeks{W-1} + - (weekday{static_cast(wd)} - Monday); - if (Y == not_a_year) - Y = static_cast(ymd_trial.year()); - else if (year{Y} != ymd_trial.year()) - goto broken; - if (m == not_a_month) - m = static_cast(static_cast(ymd_trial.month())); - else if (month(static_cast(m)) != ymd_trial.month()) - goto broken; - if (d == not_a_day) - d = static_cast(static_cast(ymd_trial.day())); - else if (day(static_cast(d)) != ymd_trial.day()) - goto broken; - computed = true; - } - if (j != not_a_doy && Y != not_a_year) - { - auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}}; - if (m == 0) - m = static_cast(static_cast(ymd_trial.month())); - else if (month(static_cast(m)) != ymd_trial.month()) - goto broken; - if (d == 0) - d = static_cast(static_cast(ymd_trial.day())); - else if (day(static_cast(d)) != ymd_trial.day()) - goto broken; - j = not_a_doy; - } - auto ymd = year{Y}/m/d; - if (ymd.ok()) - { - if (wd == not_a_weekday) - wd = static_cast((weekday(sys_days(ymd)) - Sunday).count()); - else if (wd != static_cast((weekday(sys_days(ymd)) - Sunday).count())) - goto broken; - if (!computed) - { - if (G != not_a_year || V != not_a_week_num) - { - sys_days sd = ymd; - auto G_trial = year_month_day{sd + days{3}}.year(); - auto start = sys_days((G_trial - years{1})/December/Thursday[last]) + - (Monday - Thursday); - if (sd < start) - { - --G_trial; - if (V != not_a_week_num) - start = sys_days((G_trial - years{1})/December/Thursday[last]) - + (Monday - Thursday); - } - if (G != not_a_year && G != static_cast(G_trial)) - goto broken; - if (V != not_a_week_num) - { - auto V_trial = duration_cast(sd - start).count() + 1; - if (V != V_trial) - goto broken; - } - } - if (U != not_a_week_num) - { - auto start = sys_days(Sunday[1]/January/ymd.year()); - auto U_trial = floor(sys_days(ymd) - start).count() + 1; - if (U != U_trial) - goto broken; - } - if (W != not_a_week_num) - { - auto start = sys_days(Monday[1]/January/ymd.year()); - auto W_trial = floor(sys_days(ymd) - start).count() + 1; - if (W != W_trial) - goto broken; - } - } - } - fds.ymd = ymd; - if (I != not_a_hour_12_value) - { - if (!(1 <= I && I <= 12)) - goto broken; - if (p != not_a_ampm) - { - // p is in [0, 1] == [AM, PM] - // Store trial H in I - if (I == 12) - --p; - I += p*12; - // Either set H from I or make sure H and I are consistent - if (H == not_a_hour) - H = I; - else if (I != H) - goto broken; - } - else // p == not_a_ampm - { - // if H, make sure H and I could be consistent - if (H != not_a_hour) - { - if (I == 12) - { - if (H != 0 && H != 12) - goto broken; - } - else if (!(I == H || I == H+12)) - { - goto broken; - } - } - } - } - if (H != not_a_hour) - { - fds.has_tod = true; - fds.tod = hh_mm_ss{hours{H}}; - } - if (M != not_a_minute) - { - fds.has_tod = true; - fds.tod.m_ = minutes{M}; - } - if (s != not_a_second) - { - fds.has_tod = true; - fds.tod.s_ = detail::decimal_format_seconds{s}; - } - if (j != not_a_doy) - { - fds.has_tod = true; - fds.tod.h_ += hours{days{j}}; - } - if (wd != not_a_weekday) - fds.wd = weekday{static_cast(wd)}; - if (abbrev != nullptr) - *abbrev = std::move(temp_abbrev); - if (offset != nullptr && temp_offset != not_a_offset) - *offset = temp_offset; + else { // !command + read(is, *fmt); } - return is; + command = nullptr; + width = -1; + modified = CharT{}; + break; + case 'b': + case 'B': + case 'h': + if (command) { + if (modified == CharT{}) { + int ttm = not_a_month; +#if !ONLY_C_LOCALE + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + ttm = tm.tm_mon + 1; + } + is.setstate(err); +#else + auto nm = detail::month_names(); + auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; + if (!is.fail()) { + ttm = i % 12 + 1; + } +#endif + checked_set(m, ttm, not_a_month, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'c': + if (command) { + if (modified != CharT{'O'}) { +#if !ONLY_C_LOCALE + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(Y, tm.tm_year + 1900, not_a_year, is); + checked_set(m, tm.tm_mon + 1, not_a_month, is); + checked_set(d, tm.tm_mday, not_a_day, is); + checked_set(H, tm.tm_hour, not_a_hour, is); + checked_set(M, tm.tm_min, not_a_minute, is); + checked_set(s, duration_cast(seconds{tm.tm_sec}), + not_a_second, is); + } + is.setstate(err); +#else + // "%a %b %e %T %Y" + auto nm = detail::weekday_names(); + auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; + checked_set(wd, static_cast(i % 7), not_a_weekday, is); + ws(is); + nm = detail::month_names(); + i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; + checked_set(m, static_cast(i % 12 + 1), not_a_month, is); + ws(is); + int td = not_a_day; + read(is, rs{td, 1, 2}); + checked_set(d, td, not_a_day, is); + ws(is); + using dfs = detail::decimal_format_seconds; + CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; + int tH; + int tM; + long double S; + read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, + CharT{':'}, rld{S, 1, w}); + checked_set(H, tH, not_a_hour, is); + checked_set(M, tM, not_a_minute, is); + checked_set(s, round(duration {S}), + not_a_second, is); + ws(is); + int tY = not_a_year; + read(is, rs{tY, 1, 4u}); + checked_set(Y, tY, not_a_year, is); +#endif + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'x': + if (command) { + if (modified != CharT{'O'}) { +#if !ONLY_C_LOCALE + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(Y, tm.tm_year + 1900, not_a_year, is); + checked_set(m, tm.tm_mon + 1, not_a_month, is); + checked_set(d, tm.tm_mday, not_a_day, is); + } + is.setstate(err); +#else + // "%m/%d/%y" + int ty = not_a_2digit_year; + int tm = not_a_month; + int td = not_a_day; + read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'}, + rs{ty, 1, 2}); + checked_set(y, ty, not_a_2digit_year, is); + checked_set(m, tm, not_a_month, is); + checked_set(d, td, not_a_day, is); +#endif + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'X': + if (command) { + if (modified != CharT{'O'}) { +#if !ONLY_C_LOCALE + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(H, tm.tm_hour, not_a_hour, is); + checked_set(M, tm.tm_min, not_a_minute, is); + checked_set(s, duration_cast(seconds{tm.tm_sec}), + not_a_second, is); + } + is.setstate(err); +#else + // "%T" + using dfs = detail::decimal_format_seconds; + CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; + int tH = not_a_hour; + int tM = not_a_minute; + long double S; + read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, + CharT{':'}, rld{S, 1, w}); + checked_set(H, tH, not_a_hour, is); + checked_set(M, tM, not_a_minute, is); + checked_set(s, round(duration {S}), + not_a_second, is); +#endif + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'C': + if (command) { + int tC = not_a_century; +#if !ONLY_C_LOCALE + if (modified == CharT {}) { +#endif + read(is, rs {tC, 1, width == -1 ? 2u : static_cast(width)}); +#if !ONLY_C_LOCALE + } + else { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + auto tY = tm.tm_year + 1900; + tC = (tY >= 0 ? tY : tY - 99) / 100; + } + is.setstate(err); + } +#endif + checked_set(C, tC, not_a_century, is); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'D': + if (command) { + if (modified == CharT{}) { + int tn = not_a_month; + int td = not_a_day; + int ty = not_a_2digit_year; + read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, + ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, + rs{ty, 1, 2}); + checked_set(y, ty, not_a_2digit_year, is); + checked_set(m, tn, not_a_month, is); + checked_set(d, td, not_a_day, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'F': + if (command) { + if (modified == CharT{}) { + int tY = not_a_year; + int tn = not_a_month; + int td = not_a_day; + read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}, + CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2}); + checked_set(Y, tY, not_a_year, is); + checked_set(m, tn, not_a_month, is); + checked_set(d, td, not_a_day, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'd': + case 'e': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + int td = not_a_day; + read(is, rs{td, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(d, td, not_a_day, is); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + command = nullptr; + width = -1; + modified = CharT{}; + if ((err & ios::failbit) == 0) { + checked_set(d, tm.tm_mday, not_a_day, is); + } + is.setstate(err); + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'H': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + int tH = not_a_hour; + read(is, ru{tH, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(H, tH, not_a_hour, is); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(H, tm.tm_hour, not_a_hour, is); + } + is.setstate(err); + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'I': + if (command) { + if (modified == CharT{}) { + int tI = not_a_hour_12_value; + // reads in an hour into I, but most be in [1, 12] + read(is, rs{tI, 1, width == -1 ? 2u : static_cast(width)}); + if (!(1 <= tI && tI <= 12)) { + is.setstate(ios::failbit); + } + checked_set(I, tI, not_a_hour_12_value, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'j': + if (command) { + if (modified == CharT{}) { + int tj = not_a_doy; + read(is, ru{tj, 1, width == -1 ? 3u : static_cast(width)}); + checked_set(j, tj, not_a_doy, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'M': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + int tM = not_a_minute; + read(is, ru{tM, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(M, tM, not_a_minute, is); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(M, tm.tm_min, not_a_minute, is); + } + is.setstate(err); + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'm': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + int tn = not_a_month; + read(is, rs{tn, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(m, tn, not_a_month, is); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(m, tm.tm_mon + 1, not_a_month, is); + } + is.setstate(err); + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'n': + case 't': + if (command) { + if (modified == CharT{}) { + // %n matches a single white space character + // %t matches 0 or 1 white space characters + auto ic = is.peek(); + if (Traits::eq_int_type(ic, Traits::eof())) { + ios::iostate err = ios::eofbit; + if (*fmt == 'n') { + err |= ios::failbit; + } + is.setstate(err); + break; + } + if (isspace(ic)) { + (void)is.get(); + } + else if (*fmt == 'n') { + is.setstate(ios::failbit); + } + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'p': + if (command) { + if (modified == CharT{}) { + int tp = not_a_ampm; +#if !ONLY_C_LOCALE + tm = std::tm {}; + tm.tm_hour = 1; + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + is.setstate(err); + if (tm.tm_hour == 1) { + tp = 0; + } + else if (tm.tm_hour == 13) { + tp = 1; + } + else { + is.setstate(err); + } +#else + auto nm = detail::ampm_names(); + auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; + tp = i; +#endif + checked_set(p, tp, not_a_ampm, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + + break; + case 'r': + if (command) { + if (modified == CharT{}) { +#if !ONLY_C_LOCALE + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(H, tm.tm_hour, not_a_hour, is); + checked_set(M, tm.tm_min, not_a_hour, is); + checked_set(s, duration_cast(seconds{tm.tm_sec}), + not_a_second, is); + } + is.setstate(err); +#else + // "%I:%M:%S %p" + using dfs = detail::decimal_format_seconds; + CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; + long double S; + int tI = not_a_hour_12_value; + int tM = not_a_minute; + read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2}, + CharT{':'}, rld{S, 1, w}); + checked_set(I, tI, not_a_hour_12_value, is); + checked_set(M, tM, not_a_minute, is); + checked_set(s, round(duration {S}), + not_a_second, is); + ws(is); + auto nm = detail::ampm_names(); + auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; + checked_set(p, static_cast(i), not_a_ampm, is); +#endif + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'R': + if (command) { + if (modified == CharT{}) { + int tH = not_a_hour; + int tM = not_a_minute; + read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'}, + ru{tM, 1, 2}, CharT{'\0'}); + checked_set(H, tH, not_a_hour, is); + checked_set(M, tM, not_a_minute, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'S': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'E'}) +#endif + { + using dfs = detail::decimal_format_seconds; + CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; + long double S; + read(is, rld{S, 1, width == -1 ? w : static_cast(width)}); + checked_set(s, round(duration {S}), + not_a_second, is); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'O'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) + checked_set(s, duration_cast(seconds{tm.tm_sec}), + not_a_second, is); + is.setstate(err); + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'T': + if (command) { + if (modified == CharT{}) { + using dfs = detail::decimal_format_seconds; + CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; + int tH = not_a_hour; + int tM = not_a_minute; + long double S; + read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, + CharT{':'}, rld{S, 1, w}); + checked_set(H, tH, not_a_hour, is); + checked_set(M, tM, not_a_minute, is); + checked_set(s, round(duration {S}), + not_a_second, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'Y': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#else + if (modified != CharT {'O'}) +#endif + { + int tY = not_a_year; + read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}); + checked_set(Y, tY, not_a_year, is); + } +#if !ONLY_C_LOCALE + else if (modified == CharT {'E'}) { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(Y, tm.tm_year + 1900, not_a_year, is); + } + is.setstate(err); + } +#endif + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'y': + if (command) { +#if !ONLY_C_LOCALE + if (modified == CharT {}) +#endif + { + int ty = not_a_2digit_year; + read(is, ru{ty, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(y, ty, not_a_2digit_year, is); + } +#if !ONLY_C_LOCALE + else { + ios::iostate err = ios::goodbit; + f.get(is, nullptr, is, err, &tm, command, fmt + 1); + if ((err & ios::failbit) == 0) { + checked_set(Y, tm.tm_year + 1900, not_a_year, is); + } + is.setstate(err); + } +#endif + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'g': + if (command) { + if (modified == CharT{}) { + int tg = not_a_2digit_year; + read(is, ru{tg, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(g, tg, not_a_2digit_year, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'G': + if (command) { + if (modified == CharT{}) { + int tG = not_a_year; + read(is, rs{tG, 1, width == -1 ? 4u : static_cast(width)}); + checked_set(G, tG, not_a_year, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'U': + if (command) { + if (modified == CharT{}) { + int tU = not_a_week_num; + read(is, ru{tU, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(U, tU, not_a_week_num, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'V': + if (command) { + if (modified == CharT{}) { + int tV = not_a_week_num; + read(is, ru{tV, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(V, tV, not_a_week_num, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'W': + if (command) { + if (modified == CharT{}) { + int tW = not_a_week_num; + read(is, ru{tW, 1, width == -1 ? 2u : static_cast(width)}); + checked_set(W, tW, not_a_week_num, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'E': + case 'O': + if (command) { + if (modified == CharT{}) { + modified = *fmt; + } + else { + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + } + else { + read(is, *fmt); + } + break; + case '%': + if (command) { + if (modified == CharT{}) + read(is, *fmt); + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + command = fmt; + } + break; + case 'z': + if (command) { + int tH, tM; + minutes toff = not_a_offset; + bool neg = false; + auto ic = is.peek(); + if (!Traits::eq_int_type(ic, Traits::eof())) { + auto c = static_cast(Traits::to_char_type(ic)); + if (c == '-') { + neg = true; + } + } + if (modified == CharT{}) { + read(is, rs{tH, 2, 2}); + if (!is.fail()) + toff = hours{std::abs(tH)}; + if (is.good()) { + ic = is.peek(); + if (!Traits::eq_int_type(ic, Traits::eof())) { + auto c = static_cast(Traits::to_char_type(ic)); + if ('0' <= c && c <= '9') { + read(is, ru{tM, 2, 2}); + if (!is.fail()) + toff += minutes{tM}; + } + } + } + } + else { + read(is, rs{tH, 1, 2}); + if (!is.fail()) + toff = hours{std::abs(tH)}; + if (is.good()) { + ic = is.peek(); + if (!Traits::eq_int_type(ic, Traits::eof())) { + auto c = static_cast(Traits::to_char_type(ic)); + if (c == ':') { + (void)is.get(); + read(is, ru{tM, 2, 2}); + if (!is.fail()) + toff += minutes{tM}; + } + } + } + } + if (neg) { + toff = -toff; + } + checked_set(temp_offset, toff, not_a_offset, is); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + case 'Z': + if (command) { + if (modified == CharT{}) { + std::basic_string buf; + while (is.rdstate() == std::ios::goodbit) { + auto i = is.rdbuf()->sgetc(); + if (Traits::eq_int_type(i, Traits::eof())) { + is.setstate(ios::eofbit); + break; + } + auto wc = Traits::to_char_type(i); + auto c = static_cast(wc); + // is c a valid time zone name or abbreviation character? + if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) || + c == '_' || c == '/' || c == '-' || c == '+')) + break; + buf.push_back(c); + is.rdbuf()->sbumpc(); + } + if (buf.empty()) { + is.setstate(ios::failbit); + } + checked_set(temp_abbrev, buf, {}, is); + } + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + else { + read(is, *fmt); + } + break; + default: + if (command) { + if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9') { + width = static_cast(*fmt) - '0'; + while ('0' <= fmt[1] && fmt[1] <= '9') { + width = 10 * width + static_cast(*++fmt) - '0'; + } + } + else { + if (modified == CharT{}) + read(is, CharT{'%'}, width, *fmt); + else + read(is, CharT{'%'}, width, modified, *fmt); + command = nullptr; + width = -1; + modified = CharT{}; + } + } + else { // !command + if (isspace(static_cast(*fmt))) { + // space matches 0 or more white space characters + if (is.good()) { + ws(is); + } + } + else { + read(is, *fmt); + } + } + break; + } } + // is.fail() || *fmt == CharT{} + if (is.rdstate() == ios::goodbit && command) { + if (modified == CharT{}) + read(is, CharT{'%'}, width); + else + read(is, CharT{'%'}, width, modified); + } + if (!is.fail()) { + if (y != not_a_2digit_year) { + // Convert y and an optional C to Y + if (!(0 <= y && y <= 99)) { + goto broken; + } + if (C == not_a_century) { + if (Y == not_a_year) { + if (y >= 69) { + C = 19; + } + else { + C = 20; + } + } + else { + C = (Y >= 0 ? Y : Y - 100) / 100; + } + } + int tY; + if (C >= 0) { + tY = 100 * C + y; + } + else { + tY = 100 * (C + 1) - (y == 0 ? 100 : y); + } + if (Y != not_a_year && Y != tY) { + goto broken; + } + Y = tY; + } + if (g != not_a_2digit_year) { + // Convert g and an optional C to G + if (!(0 <= g && g <= 99)) { + goto broken; + } + if (C == not_a_century) { + if (G == not_a_year) { + if (g >= 69) { + C = 19; + } + else { + C = 20; + } + } + else { + C = (G >= 0 ? G : G - 100) / 100; + } + } + int tG; + if (C >= 0) { + tG = 100 * C + g; + } + else { + tG = 100 * (C + 1) - (g == 0 ? 100 : g); + } + if (G != not_a_year && G != tG) { + goto broken; + } + G = tG; + } + if (Y < static_cast(year::min()) || Y > static_cast(year::max())) { + Y = not_a_year; + } + bool computed = false; + if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday) { + year_month_day ymd_trial = sys_days(year{G - 1} / December / Thursday[last]) + + (Monday - Thursday) + weeks{V - 1} + + (weekday{static_cast(wd)} -Monday); + if (Y == not_a_year) { + Y = static_cast(ymd_trial.year()); + } + else if (year{Y} != ymd_trial.year()) + goto broken; + if (m == not_a_month) { + m = static_cast(static_cast(ymd_trial.month())); + } + else if (month(static_cast(m)) != ymd_trial.month()) { + goto broken; + } + if (d == not_a_day) { + d = static_cast(static_cast(ymd_trial.day())); + } + else if (day(static_cast(d)) != ymd_trial.day()) { + goto broken; + } + computed = true; + } + if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday) { + year_month_day ymd_trial = sys_days(year{Y} / January / Sunday[1]) + + weeks{U - 1} + + (weekday{static_cast(wd)} - Sunday); + if (Y == not_a_year) { + Y = static_cast(ymd_trial.year()); + } + else if (year{Y} != ymd_trial.year()) + goto broken; + if (m == not_a_month) { + m = static_cast(static_cast(ymd_trial.month())); + } + else if (month(static_cast(m)) != ymd_trial.month()) { + goto broken; + } + if (d == not_a_day) { + d = static_cast(static_cast(ymd_trial.day())); + } + else if (day(static_cast(d)) != ymd_trial.day()) { + goto broken; + } + computed = true; + } + if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday) { + year_month_day ymd_trial = sys_days(year{Y} / January / Monday[1]) + + weeks{W - 1} + + (weekday{static_cast(wd)} - Monday); + if (Y == not_a_year) { + Y = static_cast(ymd_trial.year()); + } + else if (year{Y} != ymd_trial.year()) + goto broken; + if (m == not_a_month) { + m = static_cast(static_cast(ymd_trial.month())); + } + else if (month(static_cast(m)) != ymd_trial.month()) { + goto broken; + } + if (d == not_a_day) { + d = static_cast(static_cast(ymd_trial.day())); + } + else if (day(static_cast(d)) != ymd_trial.day()) { + goto broken; + } + computed = true; + } + if (j != not_a_doy && Y != not_a_year) { + auto ymd_trial = year_month_day{local_days(year{Y} / 1 / 1) + days{j - 1}}; + if (m == 0) { + m = static_cast(static_cast(ymd_trial.month())); + } + else if (month(static_cast(m)) != ymd_trial.month()) { + goto broken; + } + if (d == 0) { + d = static_cast(static_cast(ymd_trial.day())); + } + else if (day(static_cast(d)) != ymd_trial.day()) { + goto broken; + } + j = not_a_doy; + } + auto ymd = year{Y} / m / d; + if (ymd.ok()) { + if (wd == not_a_weekday) { + wd = static_cast((weekday(sys_days(ymd)) - Sunday).count()); + } + else if (wd != static_cast((weekday(sys_days(ymd)) - Sunday).count())) { + goto broken; + } + if (!computed) { + if (G != not_a_year || V != not_a_week_num) { + sys_days sd = ymd; + auto G_trial = year_month_day{sd + days{3}}.year(); + auto start = sys_days((G_trial - years{1}) / December / Thursday[last]) + + (Monday - Thursday); + if (sd < start) { + --G_trial; + if (V != not_a_week_num) + start = sys_days((G_trial - years{1}) / December / Thursday[last]) + + (Monday - Thursday); + } + if (G != not_a_year && G != static_cast(G_trial)) { + goto broken; + } + if (V != not_a_week_num) { + auto V_trial = duration_cast(sd - start).count() + 1; + if (V != V_trial) { + goto broken; + } + } + } + if (U != not_a_week_num) { + auto start = sys_days(Sunday[1] / January / ymd.year()); + auto U_trial = floor(sys_days(ymd) - start).count() + 1; + if (U != U_trial) { + goto broken; + } + } + if (W != not_a_week_num) { + auto start = sys_days(Monday[1] / January / ymd.year()); + auto W_trial = floor(sys_days(ymd) - start).count() + 1; + if (W != W_trial) { + goto broken; + } + } + } + } + fds.ymd = ymd; + if (I != not_a_hour_12_value) { + if (!(1 <= I && I <= 12)) { + goto broken; + } + if (p != not_a_ampm) { + // p is in [0, 1] == [AM, PM] + // Store trial H in I + if (I == 12) { + --p; + } + I += p * 12; + // Either set H from I or make sure H and I are consistent + if (H == not_a_hour) { + H = I; + } + else if (I != H) { + goto broken; + } + } + else { // p == not_a_ampm + // if H, make sure H and I could be consistent + if (H != not_a_hour) { + if (I == 12) { + if (H != 0 && H != 12) { + goto broken; + } + } + else if (!(I == H || I == H + 12)) { + goto broken; + } + } + } + } + if (H != not_a_hour) { + fds.has_tod = true; + fds.tod = hh_mm_ss {hours{H}}; + } + if (M != not_a_minute) { + fds.has_tod = true; + fds.tod.m_ = minutes{M}; + } + if (s != not_a_second) { + fds.has_tod = true; + fds.tod.s_ = detail::decimal_format_seconds {s}; + } + if (j != not_a_doy) { + fds.has_tod = true; + fds.tod.h_ += hours{days{j}}; + } + if (wd != not_a_weekday) + fds.wd = weekday{static_cast(wd)}; + if (abbrev != nullptr) { + *abbrev = std::move(temp_abbrev); + } + if (offset != nullptr && temp_offset != not_a_offset) { + *offset = temp_offset; + } + } + return is; + } broken: - is.setstate(ios::failbit); - return is; + is.setstate(ios::failbit); + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, year& y, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, year &y, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.year().ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - y = fds.ymd.year(); - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.year().ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + y = fds.ymd.year(); + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, month& m, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, month &m, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.month().ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - m = fds.ymd.month(); - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.month().ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + m = fds.ymd.month(); + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, day& d, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, day &d, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.day().ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - d = fds.ymd.day(); - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.day().ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + d = fds.ymd.day(); + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, weekday& wd, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, weekday &wd, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.wd.ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - wd = fds.wd; - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.wd.ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + wd = fds.wd; + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, year_month& ym, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, year_month &ym, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.month().ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - ym = fds.ymd.year()/fds.ymd.month(); - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.month().ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + ym = fds.ymd.year() / fds.ymd.month(); + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, month_day& md, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, month_day &md, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.month().ok() || !fds.ymd.day().ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - md = fds.ymd.month()/fds.ymd.day(); - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.month().ok() || !fds.ymd.day().ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + md = fds.ymd.month() / fds.ymd.day(); + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, - year_month_day& ymd, std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, + year_month_day &ymd, std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = std::chrono::seconds; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.ok()) - is.setstate(std::ios::failbit); - if (!is.fail()) - ymd = fds.ymd; - return is; + using CT = std::chrono::seconds; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.ok()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + ymd = fds.ymd; + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, - sys_time& tp, std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, + sys_time &tp, std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = typename std::common_type::type; - std::chrono::minutes offset_local{}; - auto offptr = offset ? offset : &offset_local; - fields fds{}; - fds.has_tod = true; - from_stream(is, fmt, fds, abbrev, offptr); - if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) - is.setstate(std::ios::failbit); - if (!is.fail()) - tp = round(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); - return is; + using CT = typename std::common_type::type; + std::chrono::minutes offset_local{}; + auto offptr = offset ? offset : &offset_local; + fields fds{}; + fds.has_tod = true; + from_stream(is, fmt, fds, abbrev, offptr); + if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + tp = round(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); + } + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, - local_time& tp, std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, + local_time &tp, std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using CT = typename std::common_type::type; - fields fds{}; - fds.has_tod = true; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) - is.setstate(std::ios::failbit); - if (!is.fail()) - tp = round(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); - return is; + using CT = typename std::common_type::type; + fields fds{}; + fds.has_tod = true; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) + tp = round(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); + return is; } template > -std::basic_istream& -from_stream(std::basic_istream& is, const CharT* fmt, - std::chrono::duration& d, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) +std::basic_istream & +from_stream(std::basic_istream &is, const CharT *fmt, + std::chrono::duration &d, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) { - using Duration = std::chrono::duration; - using CT = typename std::common_type::type; - fields fds{}; - from_stream(is, fmt, fds, abbrev, offset); - if (!fds.has_tod) - is.setstate(std::ios::failbit); - if (!is.fail()) - d = std::chrono::duration_cast(fds.tod.to_duration()); - return is; + using Duration = std::chrono::duration; + using CT = typename std::common_type::type; + fields fds{}; + from_stream(is, fmt, fds, abbrev, offset); + if (!fds.has_tod) { + is.setstate(std::ios::failbit); + } + if (!is.fail()) { + d = std::chrono::duration_cast(fds.tod.to_duration()); + } + return is; } template , class Alloc = std::allocator> -struct parse_manip -{ - const std::basic_string format_; - Parsable& tp_; - std::basic_string* abbrev_; - std::chrono::minutes* offset_; +struct parse_manip { + const std::basic_string format_; + Parsable &tp_; + std::basic_string *abbrev_; + std::chrono::minutes *offset_; public: - parse_manip(std::basic_string format, Parsable& tp, - std::basic_string* abbrev = nullptr, - std::chrono::minutes* offset = nullptr) - : format_(std::move(format)) - , tp_(tp) - , abbrev_(abbrev) - , offset_(offset) - {} + parse_manip(std::basic_string format, Parsable &tp, + std::basic_string *abbrev = nullptr, + std::chrono::minutes *offset = nullptr) + : format_(std::move(format)) + , tp_(tp) + , abbrev_(abbrev) + , offset_(offset) + {} }; template -std::basic_istream& -operator>>(std::basic_istream& is, - const parse_manip& x) +std::basic_istream & +operator>>(std::basic_istream &is, + const parse_manip &x) { - return from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_); + return from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_); } template inline auto -parse(const std::basic_string& format, Parsable& tp) - -> decltype(from_stream(std::declval&>(), - format.c_str(), tp), - parse_manip{format, tp}) +parse(const std::basic_string &format, Parsable &tp) +-> decltype(from_stream(std::declval&>(), + format.c_str(), tp), + parse_manip { - return {format, tp}; + format, tp +}) +{ + return {format, tp}; } template inline auto -parse(const std::basic_string& format, Parsable& tp, - std::basic_string& abbrev) - -> decltype(from_stream(std::declval&>(), - format.c_str(), tp, &abbrev), - parse_manip{format, tp, &abbrev}) +parse(const std::basic_string &format, Parsable &tp, + std::basic_string &abbrev) +-> decltype(from_stream(std::declval&>(), + format.c_str(), tp, &abbrev), + parse_manip { - return {format, tp, &abbrev}; + format, tp, &abbrev +}) +{ + return {format, tp, &abbrev}; } template inline auto -parse(const std::basic_string& format, Parsable& tp, - std::chrono::minutes& offset) - -> decltype(from_stream(std::declval&>(), - format.c_str(), tp, - std::declval*>(), - &offset), - parse_manip{format, tp, nullptr, &offset}) +parse(const std::basic_string &format, Parsable &tp, + std::chrono::minutes &offset) +-> decltype(from_stream(std::declval&>(), + format.c_str(), tp, + std::declval*>(), + &offset), + parse_manip { - return {format, tp, nullptr, &offset}; + format, tp, nullptr, &offset +}) +{ + return {format, tp, nullptr, &offset}; } template inline auto -parse(const std::basic_string& format, Parsable& tp, - std::basic_string& abbrev, std::chrono::minutes& offset) - -> decltype(from_stream(std::declval&>(), - format.c_str(), tp, &abbrev, &offset), - parse_manip{format, tp, &abbrev, &offset}) +parse(const std::basic_string &format, Parsable &tp, + std::basic_string &abbrev, std::chrono::minutes &offset) +-> decltype(from_stream(std::declval&>(), + format.c_str(), tp, &abbrev, &offset), + parse_manip { - return {format, tp, &abbrev, &offset}; + format, tp, &abbrev, &offset +}) +{ + return {format, tp, &abbrev, &offset}; } // const CharT* formats @@ -7863,57 +7724,69 @@ parse(const std::basic_string& format, Parsable& tp, template inline auto -parse(const CharT* format, Parsable& tp) - -> decltype(from_stream(std::declval&>(), format, tp), - parse_manip{format, tp}) +parse(const CharT *format, Parsable &tp) +-> decltype(from_stream(std::declval&>(), format, tp), + parse_manip { - return {format, tp}; + format, tp +}) +{ + return {format, tp}; } template inline auto -parse(const CharT* format, Parsable& tp, std::basic_string& abbrev) - -> decltype(from_stream(std::declval&>(), format, - tp, &abbrev), - parse_manip{format, tp, &abbrev}) +parse(const CharT *format, Parsable &tp, std::basic_string &abbrev) +-> decltype(from_stream(std::declval&>(), format, + tp, &abbrev), + parse_manip { - return {format, tp, &abbrev}; + format, tp, &abbrev +}) +{ + return {format, tp, &abbrev}; } template inline auto -parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset) - -> decltype(from_stream(std::declval&>(), format, - tp, std::declval*>(), &offset), - parse_manip{format, tp, nullptr, &offset}) +parse(const CharT *format, Parsable &tp, std::chrono::minutes &offset) +-> decltype(from_stream(std::declval&>(), format, + tp, std::declval*>(), &offset), + parse_manip { - return {format, tp, nullptr, &offset}; + format, tp, nullptr, &offset +}) +{ + return {format, tp, nullptr, &offset}; } template inline auto -parse(const CharT* format, Parsable& tp, - std::basic_string& abbrev, std::chrono::minutes& offset) - -> decltype(from_stream(std::declval&>(), format, - tp, &abbrev, &offset), - parse_manip{format, tp, &abbrev, &offset}) +parse(const CharT *format, Parsable &tp, + std::basic_string &abbrev, std::chrono::minutes &offset) +-> decltype(from_stream(std::declval&>(), format, + tp, &abbrev, &offset), + parse_manip { - return {format, tp, &abbrev, &offset}; + format, tp, &abbrev, &offset +}) +{ + return {format, tp, &abbrev, &offset}; } // duration streaming template inline -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::chrono::duration& d) +std::basic_ostream & +operator<<(std::basic_ostream &os, + const std::chrono::duration &d) { - return os << detail::make_string::from(d.count()) + - detail::get_units(typename Period::type{}); + return os << detail::make_string::from(d.count()) + + detail::get_units(typename Period::type{}); } } // namespace date diff --git a/include/satnogs/debug_msg_source.h b/include/satnogs/debug_msg_source.h index ffc366f..4a0ecc5 100644 --- a/include/satnogs/debug_msg_source.h +++ b/include/satnogs/debug_msg_source.h @@ -24,33 +24,30 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief A block for debug reasons producing specific messages - * \ingroup satnogs - * - */ - class SATNOGS_API debug_msg_source : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief A block for debug reasons producing specific messages + * \ingroup satnogs + * + */ +class SATNOGS_API debug_msg_source : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /** - * Debug message source block. - * @param msg the message - * @param delay delay in seconds between consecutive messages - * @param repeat if set to yes the block will produce a message every - * \p delay seconds - */ - static sptr - make (const std::string &msg, double delay, bool repeat = true); - }; + /** + * Debug message source block. + * @param msg the message + * @param delay delay in seconds between consecutive messages + * @param repeat if set to yes the block will produce a message every + * \p delay seconds + */ + static sptr + make(const std::string &msg, double delay, bool repeat = true); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DEBUG_MSG_SOURCE_H */ diff --git a/include/satnogs/debug_msg_source_raw.h b/include/satnogs/debug_msg_source_raw.h index 0313397..9be979c 100644 --- a/include/satnogs/debug_msg_source_raw.h +++ b/include/satnogs/debug_msg_source_raw.h @@ -24,35 +24,32 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief A block for debug reasons producing specific messages. - * The input message can be anything, opposed to the \p debug_msg_source() - * block that can accept only string messages. - * \ingroup satnogs - * - */ - class SATNOGS_API debug_msg_source_raw : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief A block for debug reasons producing specific messages. + * The input message can be anything, opposed to the \p debug_msg_source() + * block that can accept only string messages. + * \ingroup satnogs + * + */ +class SATNOGS_API debug_msg_source_raw : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /** - * Debug message source block. - * @param msg the message - * @param delay delay in seconds between consecutive messages - * @param repeat if set to yes the block will produce a message every - * \p delay seconds - */ - static sptr - make (const std::vector &msg, double delay, bool repeat); - }; + /** + * Debug message source block. + * @param msg the message + * @param delay delay in seconds between consecutive messages + * @param repeat if set to yes the block will produce a message every + * \p delay seconds + */ + static sptr + make(const std::vector &msg, double delay, bool repeat); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DEBUG_MSG_SOURCE_RAW_H */ diff --git a/include/satnogs/decoder.h b/include/satnogs/decoder.h index 4603cef..ea705b8 100644 --- a/include/satnogs/decoder.h +++ b/include/satnogs/decoder.h @@ -26,22 +26,19 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /** * The status of the decoder */ -class decoder_status -{ +class decoder_status { public: int consumed; /**< The number of input items consumed */ bool decode_success; /**< Indicated if there was a successful decoding */ pmt::pmt_t data; /**< a dictionary with the PDU with of decoded data and the corresponding metadata for the decoded frame */ - decoder_status () : + decoder_status() : consumed(0), decode_success(false), data(pmt::make_dict()) @@ -63,18 +60,17 @@ typedef class decoder_status decoder_status_t; * appropriate decoder class that implements this abstract class API. * */ -class SATNOGS_API decoder -{ +class SATNOGS_API decoder { public: typedef boost::shared_ptr decoder_sptr; static int base_unique_id; int - unique_id (); + unique_id(); - decoder (int input_item_size, size_t max_frame_len = 8192); - virtual ~decoder (); + decoder(int input_item_size, size_t max_frame_len = 8192); + virtual ~decoder(); /** * Decodes a buffer. The difference with the decoder::decode_once() is that @@ -95,7 +91,7 @@ public: * If an error occurred an appropriate negative error code is returned */ virtual decoder_status_t - decode (const void *in, int len) = 0; + decode(const void *in, int len) = 0; /** @@ -103,7 +99,7 @@ public: * */ virtual void - reset () = 0; + reset() = 0; size_t max_frame_len() const; diff --git a/include/satnogs/doppler_correction_cc.h b/include/satnogs/doppler_correction_cc.h index 4d73603..e7e90b2 100644 --- a/include/satnogs/doppler_correction_cc.h +++ b/include/satnogs/doppler_correction_cc.h @@ -24,42 +24,39 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief This block corrects the doppler effect between the ground - * station and the satellite. It takes the imput stream in baseband - * and applies proper corrections to keep the carrier at the desired - * frequency. To achieve that it uses messages containing the absolute - * predicted frequency of the satellite from software like Gpredict. - * - * \ingroup satnogs - * - */ - class SATNOGS_API doppler_correction_cc : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief This block corrects the doppler effect between the ground + * station and the satellite. It takes the imput stream in baseband + * and applies proper corrections to keep the carrier at the desired + * frequency. To achieve that it uses messages containing the absolute + * predicted frequency of the satellite from software like Gpredict. + * + * \ingroup satnogs + * + */ +class SATNOGS_API doppler_correction_cc : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * The doppler correction block. The input is the complex signal at - * baseband as it comes from the SDR device. The message input \p freq - * received periodically messages containing the predicted absolute - * frequency of the satellite at that specific time. - * @param target_freq the absolute frequency of the satellite - * @param sampling_rate the sampling rate of the signal - * @param corrections_per_sec the number of the corrections every second - * that the block should perform - */ - static sptr - make (double target_freq, double sampling_rate, - size_t corrections_per_sec = 1000); - }; + /*! + * The doppler correction block. The input is the complex signal at + * baseband as it comes from the SDR device. The message input \p freq + * received periodically messages containing the predicted absolute + * frequency of the satellite at that specific time. + * @param target_freq the absolute frequency of the satellite + * @param sampling_rate the sampling rate of the signal + * @param corrections_per_sec the number of the corrections every second + * that the block should perform + */ + static sptr + make(double target_freq, double sampling_rate, + size_t corrections_per_sec = 1000); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_H */ diff --git a/include/satnogs/doppler_fit.h b/include/satnogs/doppler_fit.h index a9f9a3b..5a1d65f 100644 --- a/include/satnogs/doppler_fit.h +++ b/include/satnogs/doppler_fit.h @@ -26,35 +26,32 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Doppler frequency polynomial fitting tool - * \ingroup satnogs - */ - class SATNOGS_API doppler_fit - { - public: - doppler_fit (size_t degree); +/*! + * \brief Doppler frequency polynomial fitting tool + * \ingroup satnogs + */ +class SATNOGS_API doppler_fit { +public: + doppler_fit(size_t degree); - void - fit (std::deque drifts); + void + fit(std::deque drifts); - void - predict_freqs (double *freqs, size_t ncorrections, - size_t samples_per_correction); + void + predict_freqs(double *freqs, size_t ncorrections, + size_t samples_per_correction); - private: - const size_t d_degree; - double d_last_x; - std::vector d_coeff; - boost::mutex d_mutex; - }; +private: + const size_t d_degree; + double d_last_x; + std::vector d_coeff; + boost::mutex d_mutex; +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DOPPLER_FIT_H */ diff --git a/include/satnogs/frame_acquisition.h b/include/satnogs/frame_acquisition.h index 4345f99..9250257 100644 --- a/include/satnogs/frame_acquisition.h +++ b/include/satnogs/frame_acquisition.h @@ -25,10 +25,8 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief A generic frame acquisition block @@ -60,8 +58,7 @@ namespace satnogs * \ingroup satnogs * */ -class SATNOGS_API frame_acquisition : virtual public gr::sync_block -{ +class SATNOGS_API frame_acquisition : virtual public gr::sync_block { public: typedef boost::shared_ptr sptr; @@ -122,9 +119,9 @@ public: */ static sptr make(variant_t variant, - const std::vector& preamble, + const std::vector &preamble, size_t preamble_threshold, - const std::vector& sync, + const std::vector &sync, size_t sync_threshold, size_t frame_size_field_len, size_t frame_len, diff --git a/include/satnogs/frame_decoder.h b/include/satnogs/frame_decoder.h index 7be15d4..36bce4d 100644 --- a/include/satnogs/frame_decoder.h +++ b/include/satnogs/frame_decoder.h @@ -26,34 +26,33 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - /*! - * \brief This is a generic frame decoder block. It takes as input a - * bit stream and produces decoded frames and their metadata. - * - * The decoding is performed by using a proper decoder object. - * Each decoder implements the virtual class ::decoder() - * - * The frame and metadata are produced in a pmt dictionary, with the - * keys "pdu" and "metadata". - * - * \ingroup satnogs - * - */ - class SATNOGS_API frame_decoder : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief This is a generic frame decoder block. It takes as input a + * bit stream and produces decoded frames and their metadata. + * + * The decoding is performed by using a proper decoder object. + * Each decoder implements the virtual class ::decoder() + * + * The frame and metadata are produced in a pmt dictionary, with the + * keys "pdu" and "metadata". + * + * \ingroup satnogs + * + */ +class SATNOGS_API frame_decoder : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * \brief Return a shared_ptr to a new instance of satnogs::frame_decoder. - * @param decoder_object the decoder object to use - */ - static sptr make(decoder::decoder_sptr decoder_object, int input_size); - }; + /*! + * \brief Return a shared_ptr to a new instance of satnogs::frame_decoder. + * @param decoder_object the decoder object to use + */ + static sptr make(decoder::decoder_sptr decoder_object, int input_size); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_FRAME_DECODER_H */ diff --git a/include/satnogs/frame_encoder.h b/include/satnogs/frame_encoder.h index 82582ca..de187e7 100644 --- a/include/satnogs/frame_encoder.h +++ b/include/satnogs/frame_encoder.h @@ -25,30 +25,29 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - /*! - * \brief <+description of block+> - * \ingroup satnogs - * - */ - class SATNOGS_API frame_encoder : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief <+description of block+> + * \ingroup satnogs + * + */ +class SATNOGS_API frame_encoder : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * \brief Return a shared_ptr to a new instance of satnogs::frame_encoder. - * - * To avoid accidental use of raw pointers, satnogs::frame_encoder's - * constructor is in a private implementation - * class. satnogs::frame_encoder::make is the public interface for - * creating new instances. - */ - static sptr make(bool append_preamble, bool ecss_encap, const std::string& dest_addr, uint8_t dest_ssid, const std::string& src_addr, uint8_t src_ssid); - }; + /*! + * \brief Return a shared_ptr to a new instance of satnogs::frame_encoder. + * + * To avoid accidental use of raw pointers, satnogs::frame_encoder's + * constructor is in a private implementation + * class. satnogs::frame_encoder::make is the public interface for + * creating new instances. + */ + static sptr make(bool append_preamble, bool ecss_encap, const std::string &dest_addr, uint8_t dest_ssid, const std::string &src_addr, uint8_t src_ssid); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_FRAME_ENCODER_H */ diff --git a/include/satnogs/frame_file_sink.h b/include/satnogs/frame_file_sink.h index 8470aa1..7661f95 100644 --- a/include/satnogs/frame_file_sink.h +++ b/include/satnogs/frame_file_sink.h @@ -24,31 +24,28 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief <+description of block+> - * \ingroup satnogs - * - */ - class SATNOGS_API frame_file_sink : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief <+description of block+> + * \ingroup satnogs + * + */ +class SATNOGS_API frame_file_sink : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /*! - * Frame to file, sink block - * @param prefix_name Prefix of the file name, including the directory path - * @param output_type Format type of the output file, txt, hex, bin - */ - static sptr - make (const std::string& prefix_name, int output_type); - }; + /*! + * Frame to file, sink block + * @param prefix_name Prefix of the file name, including the directory path + * @param output_type Format type of the output file, txt, hex, bin + */ + static sptr + make(const std::string &prefix_name, int output_type); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_FRAME_FILE_SINK_H */ diff --git a/include/satnogs/freq_drift.h b/include/satnogs/freq_drift.h index f5edd19..106e2a7 100644 --- a/include/satnogs/freq_drift.h +++ b/include/satnogs/freq_drift.h @@ -24,36 +24,33 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Class that specifies the frequency drift at a given time. - * The time is measured in samples. - * \ingroup satnogs - */ - class SATNOGS_API freq_drift - { - public: - freq_drift (uint64_t x, double y); - ~freq_drift (); - double - get_freq_drift () const; - void - set_freq_drift (double freqDrift); - uint64_t - get_x () const; - void - set_x (uint64_t x); +/*! + * \brief Class that specifies the frequency drift at a given time. + * The time is measured in samples. + * \ingroup satnogs + */ +class SATNOGS_API freq_drift { +public: + freq_drift(uint64_t x, double y); + ~freq_drift(); + double + get_freq_drift() const; + void + set_freq_drift(double freqDrift); + uint64_t + get_x() const; + void + set_x(uint64_t x); - private: - uint64_t d_x; - double d_freq_drift; - }; +private: + uint64_t d_x; + double d_freq_drift; +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_FREQ_DRIFT_H */ diff --git a/include/satnogs/golay24.h b/include/satnogs/golay24.h index f34c605..949e524 100644 --- a/include/satnogs/golay24.h +++ b/include/satnogs/golay24.h @@ -27,10 +27,8 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief A binary Golay (24,12,8) encoder and decoder. @@ -42,11 +40,10 @@ namespace satnogs * John Wiley & Sons, 2006. * */ -class SATNOGS_API golay24 -{ +class SATNOGS_API golay24 { public: - golay24 (); - ~golay24 (); + golay24(); + ~golay24(); static const std::vector G_P; static const std::vector G_I; diff --git a/include/satnogs/ieee802_15_4_variant_decoder.h b/include/satnogs/ieee802_15_4_variant_decoder.h index c532b26..a0665e0 100644 --- a/include/satnogs/ieee802_15_4_variant_decoder.h +++ b/include/satnogs/ieee802_15_4_variant_decoder.h @@ -25,10 +25,8 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief A IEEE 802.15.4 like decoder @@ -40,15 +38,14 @@ namespace satnogs * scheme. * */ -class SATNOGS_API ieee802_15_4_variant_decoder -{ +class SATNOGS_API ieee802_15_4_variant_decoder { public: - ieee802_15_4_variant_decoder (const std::vector &preamble, - size_t preamble_threshold, - const std::vector &sync, - crc::crc_t crc, - whitening::whitening_sptr descrambler); - ~ieee802_15_4_variant_decoder (); + ieee802_15_4_variant_decoder(const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + crc::crc_t crc, + whitening::whitening_sptr descrambler); + ~ieee802_15_4_variant_decoder(); private: }; diff --git a/include/satnogs/iq_sink.h b/include/satnogs/iq_sink.h index 52773f3..23e9ff2 100644 --- a/include/satnogs/iq_sink.h +++ b/include/satnogs/iq_sink.h @@ -25,47 +25,44 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief This block converts a complex float input stream to short and stores +/*! + * \brief This block converts a complex float input stream to short and stores + * it to a file. If the value of status argument is zero the block behaves + * as a null sink block. + * + * \ingroup satnogs + * + */ +class SATNOGS_API iq_sink : virtual public gr::sync_block, + virtual public gr::blocks::file_sink_base { +public: + typedef boost::shared_ptr sptr; + + /** + * This block converts a complex float input stream to short and stores * it to a file. If the value of status argument is zero the block behaves * as a null sink block. * - * \ingroup satnogs + * @param scale the value multiplied against each point in the input stream + * @param filename name of the file to open and write output to. + * @param append if true, data is appended to the file instead of + * overwriting the initial content. + * @param status the status of the block. + * - 0: Block acts as a null sink + * - 1: Active * + * @return a shared_ptr to a new instance of satnogs::iq_sink. */ - class SATNOGS_API iq_sink : virtual public gr::sync_block, - virtual public gr::blocks::file_sink_base - { - public: - typedef boost::shared_ptr sptr; - - /** - * This block converts a complex float input stream to short and stores - * it to a file. If the value of status argument is zero the block behaves - * as a null sink block. - * - * @param scale the value multiplied against each point in the input stream - * @param filename name of the file to open and write output to. - * @param append if true, data is appended to the file instead of - * overwriting the initial content. - * @param status the status of the block. - * - 0: Block acts as a null sink - * - 1: Active - * - * @return a shared_ptr to a new instance of satnogs::iq_sink. - */ - static sptr make(const float scale, - const char *filename, bool append=false, - const int status = 0); - }; + static sptr make(const float scale, + const char *filename, bool append = false, + const int status = 0); +}; } - // namespace satnogs +// namespace satnogs }// namespace gr #endif /* INCLUDED_SATNOGS_IQ_SINK_H */ diff --git a/include/satnogs/json_converter.h b/include/satnogs/json_converter.h index a3ca9ce..005ea26 100644 --- a/include/satnogs/json_converter.h +++ b/include/satnogs/json_converter.h @@ -24,10 +24,8 @@ #include #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief This block takes a PMT message from the SatNOGS decoders @@ -36,24 +34,23 @@ namespace satnogs * \ingroup satnogs * */ -class SATNOGS_API json_converter : virtual public gr::block -{ +class SATNOGS_API json_converter : virtual public gr::block { public: typedef boost::shared_ptr sptr; - /** - * This block takes a PMT message from the SatNOGS decoders - * and converts it a PMT containing the same message in JSON form. - * This can be used for debugging and stream operations. - * - * @param extra every JSON frame can contain an arbitrary amount of extra information. - * Use this fill to provide a JSON-valid string with such information. - * - * @return shared pointer of the block instance - */ + /** + * This block takes a PMT message from the SatNOGS decoders + * and converts it a PMT containing the same message in JSON form. + * This can be used for debugging and stream operations. + * + * @param extra every JSON frame can contain an arbitrary amount of extra information. + * Use this fill to provide a JSON-valid string with such information. + * + * @return shared pointer of the block instance + */ static sptr - make (const std::string& extra = ""); + make(const std::string &extra = ""); }; } // namespace satnogs diff --git a/include/satnogs/log.h b/include/satnogs/log.h index ea9378c..a7139a1 100644 --- a/include/satnogs/log.h +++ b/include/satnogs/log.h @@ -30,22 +30,22 @@ #if ENABLE_DEBUG_MSG -#define LOG_INFO(M, ...) \ - fprintf(stderr, "[INFO]: " M " \n", ##__VA_ARGS__) +#define LOG_INFO(M, ...) \ + fprintf(stderr, "[INFO]: " M " \n", ##__VA_ARGS__) #else #define LOG_INFO(M, ...) #endif -#define LOG_ERROR(M, ...) \ - fprintf(stderr, "[ERROR] %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define LOG_ERROR(M, ...) \ + fprintf(stderr, "[ERROR] %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) -#define LOG_WARN(M, ...) \ - fprintf(stderr, "[WARNING] %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define LOG_WARN(M, ...) \ + fprintf(stderr, "[WARNING] %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) #if ENABLE_DEBUG_MSG -#define LOG_DEBUG(M, ...) \ - fprintf(stderr, "[DEBUG]: " M "\n", ##__VA_ARGS__) +#define LOG_DEBUG(M, ...) \ + fprintf(stderr, "[DEBUG]: " M "\n", ##__VA_ARGS__) #else #define LOG_DEBUG(M, ...) #endif diff --git a/include/satnogs/lrpt_decoder.h b/include/satnogs/lrpt_decoder.h index 74a49e1..7a5724c 100644 --- a/include/satnogs/lrpt_decoder.h +++ b/include/satnogs/lrpt_decoder.h @@ -24,18 +24,15 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief <+description of block+> * \ingroup satnogs * */ -class SATNOGS_API lrpt_decoder : virtual public gr::block -{ +class SATNOGS_API lrpt_decoder : virtual public gr::block { public: typedef boost::shared_ptr sptr; @@ -48,7 +45,7 @@ public: * creating new instances. */ static sptr - make (); + make(); }; } // namespace satnogs diff --git a/include/satnogs/lrpt_sync.h b/include/satnogs/lrpt_sync.h index 603fcf2..0b2deba 100644 --- a/include/satnogs/lrpt_sync.h +++ b/include/satnogs/lrpt_sync.h @@ -24,18 +24,15 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief <+description of block+> * \ingroup satnogs * */ -class SATNOGS_API lrpt_sync : virtual public gr::sync_block -{ +class SATNOGS_API lrpt_sync : virtual public gr::sync_block { public: typedef boost::shared_ptr sptr; @@ -48,7 +45,7 @@ public: * creating new instances. */ static sptr - make (size_t threshold = 2); + make(size_t threshold = 2); }; } // namespace satnogs diff --git a/include/satnogs/metadata.h b/include/satnogs/metadata.h index 45406e6..7e2b174 100644 --- a/include/satnogs/metadata.h +++ b/include/satnogs/metadata.h @@ -32,10 +32,9 @@ namespace gr { namespace satnogs { -class SATNOGS_API metadata -{ +class SATNOGS_API metadata { public: - typedef enum key{ + typedef enum key { PDU = 0, CRC_VALID, FREQ_OFFSET, @@ -48,7 +47,7 @@ public: } key_t; static std::string - value(const key_t& k); + value(const key_t &k); static std::string keys(); @@ -78,7 +77,7 @@ public: add_corrected_bits(pmt::pmt_t &m, uint32_t cnt); static Json::Value - to_json(const pmt::pmt_t& m); + to_json(const pmt::pmt_t &m); }; } // namespace satnogs diff --git a/include/satnogs/morse_debug_source.h b/include/satnogs/morse_debug_source.h index fd0f489..ce6bf3c 100644 --- a/include/satnogs/morse_debug_source.h +++ b/include/satnogs/morse_debug_source.h @@ -25,47 +25,44 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief A Morse debug source block that supports injection of random - * errors based on a Bernulli distribution with probability p. - * - * \ingroup satnogs - * - */ - class SATNOGS_API morse_debug_source : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief A Morse debug source block that supports injection of random + * errors based on a Bernulli distribution with probability p. + * + * \ingroup satnogs + * + */ +class SATNOGS_API morse_debug_source : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /*! - * \brief A Morse debug source block that produces messages corresponding - * to Morse symbols, based on the given debug_seq string. - * This block can also inject random errors, based on a Bernoulli - * distribution. - * - * @param wpm words per minute - * @param debug_seq A string containing the debug sentence - * @param inject_errors if set the debug source block will produce - * errors that follow a Bernoulli distribution - * @param error_prob the probability p of error for the Bernulli distribution - * @param seq_pause_ms pause in milliseconds between concecutive debug - * sequences. For simplicity the pause duration will be scaled to multiple - * dot durations. - */ - static sptr - make (const size_t wpm, - const std::string& debug_seq, - bool inject_errors = false, - float error_prob = 0.1, - size_t seq_pause_ms = 1000); - }; + /*! + * \brief A Morse debug source block that produces messages corresponding + * to Morse symbols, based on the given debug_seq string. + * This block can also inject random errors, based on a Bernoulli + * distribution. + * + * @param wpm words per minute + * @param debug_seq A string containing the debug sentence + * @param inject_errors if set the debug source block will produce + * errors that follow a Bernoulli distribution + * @param error_prob the probability p of error for the Bernulli distribution + * @param seq_pause_ms pause in milliseconds between concecutive debug + * sequences. For simplicity the pause duration will be scaled to multiple + * dot durations. + */ + static sptr + make(const size_t wpm, + const std::string &debug_seq, + bool inject_errors = false, + float error_prob = 0.1, + size_t seq_pause_ms = 1000); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_MORSE_DEBUG_SOURCE_H */ diff --git a/include/satnogs/morse_decoder.h b/include/satnogs/morse_decoder.h index 330580d..ac90d62 100644 --- a/include/satnogs/morse_decoder.h +++ b/include/satnogs/morse_decoder.h @@ -25,30 +25,29 @@ #include namespace gr { - namespace satnogs { - /*! - * \brief Morse code decoder block. - * - * This block received messages from the previous blocks - * and try to decode the dot and dashes into clear text. - */ - class SATNOGS_API morse_decoder : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +namespace satnogs { +/*! + * \brief Morse code decoder block. + * + * This block received messages from the previous blocks + * and try to decode the dot and dashes into clear text. + */ +class SATNOGS_API morse_decoder : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /*! - * Creates a Morse decoder block - * @param unrecognized_char the character that will be placed - * in situations where the decoder can not decide which character - * was received. - * @param min_frame_len the minimum frame length in order to reduce - * false alarms - */ - static sptr make(char unrecognized_char = '#', size_t min_frame_len = 3); - }; + /*! + * Creates a Morse decoder block + * @param unrecognized_char the character that will be placed + * in situations where the decoder can not decide which character + * was received. + * @param min_frame_len the minimum frame length in order to reduce + * false alarms + */ + static sptr make(char unrecognized_char = '#', size_t min_frame_len = 3); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_MORSE_DECODER_H */ diff --git a/include/satnogs/morse_tree.h b/include/satnogs/morse_tree.h index b879012..fb73925 100644 --- a/include/satnogs/morse_tree.h +++ b/include/satnogs/morse_tree.h @@ -26,80 +26,76 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Binary tree node containing the corresponding character - */ - class SATNOGS_API tree_node - { - private: - const char d_char; - tree_node *d_left; - tree_node *d_right; +/*! + * \brief Binary tree node containing the corresponding character + */ +class SATNOGS_API tree_node { +private: + const char d_char; + tree_node *d_left; + tree_node *d_right; - public: - tree_node (char c); +public: + tree_node(char c); - void - set_left_child (tree_node *child); + void + set_left_child(tree_node *child); - void - set_right_child (tree_node *child); + void + set_right_child(tree_node *child); - tree_node* - get_left_child (); + tree_node * + get_left_child(); - tree_node* - get_right_child (); + tree_node * + get_right_child(); - char - get_char (); - }; + char + get_char(); +}; - /*! - * \brief A Binary tree representation of the Morse coding scheme. - * Left transitions occur when a dot is received, whereas right transitions - * are performed during the reception of a dash. - * - * The tree follows the ITU International Morse code representation - * ITU-R M.1677-1 - */ - class SATNOGS_API morse_tree - { - public: - morse_tree (); - morse_tree (char unrecognized); - ~morse_tree (); - void - reset (); - bool - received_symbol (morse_symbol_t s); - std::string - get_word (); - size_t - get_max_word_len () const; - size_t - get_word_len (); +/*! + * \brief A Binary tree representation of the Morse coding scheme. + * Left transitions occur when a dot is received, whereas right transitions + * are performed during the reception of a dash. + * + * The tree follows the ITU International Morse code representation + * ITU-R M.1677-1 + */ +class SATNOGS_API morse_tree { +public: + morse_tree(); + morse_tree(char unrecognized); + ~morse_tree(); + void + reset(); + bool + received_symbol(morse_symbol_t s); + std::string + get_word(); + size_t + get_max_word_len() const; + size_t + get_word_len(); - private: - const char d_unrecognized_symbol; - tree_node *d_root; - tree_node *d_current; - const size_t d_buff_len; - size_t d_word_len; - std::unique_ptr d_word_buffer; +private: + const char d_unrecognized_symbol; + tree_node *d_root; + tree_node *d_current; + const size_t d_buff_len; + size_t d_word_len; + std::unique_ptr d_word_buffer; - void - construct_tree (); - void - delete_tree (tree_node *node); - }; + void + construct_tree(); + void + delete_tree(tree_node *node); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_MORSE_TREE_H */ diff --git a/include/satnogs/multi_format_msg_sink.h b/include/satnogs/multi_format_msg_sink.h index 9061f33..3c311a4 100644 --- a/include/satnogs/multi_format_msg_sink.h +++ b/include/satnogs/multi_format_msg_sink.h @@ -24,47 +24,44 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Block accepting clear text messages from various decoders. - * Its purpose is to forward these messages at other services, programs, - * stdout, etc, - * - * \ingroup satnogs - * - */ - class SATNOGS_API multi_format_msg_sink : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief Block accepting clear text messages from various decoders. + * Its purpose is to forward these messages at other services, programs, + * stdout, etc, + * + * \ingroup satnogs + * + */ +class SATNOGS_API multi_format_msg_sink : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /*! - * \brief Block accepting clear text messages from various decoders. - * Its purpose is to either print these messages to stdout or save them - * in text format in a file. - * - * Depending on format parameter, the contents of each message are - * converted to hexademical, binary or ASCII format. - * - * @param format the format that will used to display the messages. - * 0: Clear Text 1: Hexademical 2: Binary - * @param timestamp if set, a ISO 8601 timestamp is inserted in front of - * each message - * @param out_stdout if set, the messages are displayed in the stdout. - * Otherwise messages are saved in a text file - * @param filepath specifies the file path of the text file - */ - static sptr - make (size_t format, bool timestamp = true, - bool out_stdout = true, - const std::string& filepath = ""); - }; + /*! + * \brief Block accepting clear text messages from various decoders. + * Its purpose is to either print these messages to stdout or save them + * in text format in a file. + * + * Depending on format parameter, the contents of each message are + * converted to hexademical, binary or ASCII format. + * + * @param format the format that will used to display the messages. + * 0: Clear Text 1: Hexademical 2: Binary + * @param timestamp if set, a ISO 8601 timestamp is inserted in front of + * each message + * @param out_stdout if set, the messages are displayed in the stdout. + * Otherwise messages are saved in a text file + * @param filepath specifies the file path of the text file + */ + static sptr + make(size_t format, bool timestamp = true, + bool out_stdout = true, + const std::string &filepath = ""); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_multi_format_MSG_SINK_H */ diff --git a/include/satnogs/noaa_apt_sink.h b/include/satnogs/noaa_apt_sink.h index e3cacdc..e1bcbdc 100644 --- a/include/satnogs/noaa_apt_sink.h +++ b/include/satnogs/noaa_apt_sink.h @@ -24,53 +24,50 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * Sink block for NOAA satellites - * \ingroup satnogs - * - */ - class SATNOGS_API noaa_apt_sink : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * Sink block for NOAA satellites + * \ingroup satnogs + * + */ +class SATNOGS_API noaa_apt_sink : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * Accepts a stream of floats in the range [0,1] which - * correspond to one sample per symbol (pixel) and - * outputs a grayscale PNG image. The user can - * choose between deriving a single PNG file for each - * width x length pixels or two PNG files corresponding to - * each one of the two different spectrum images contained - * in a NOAA APT transmission. The notation 'left' and 'right' - * is with respect to the original image sent by the satellite. - * Further, this block performs normalization on the input - * float values based on the max and min values observed in the stream. - * Adding to that, the user has the option to synchronize to the first of the - * two training sequences used by the NOAA APT protocol so that - * the two images are displayed one next to the other. The user - * can also select to rotate the image 180 degrees in case the captured one - * is upside down. - * - * - * @param filename_png the base filename of the output PNG file(s) - * @param width the width of the image in the APT transmission - * @param height the height of the image in the APT transmission - * @param sync user option for synchronizing to the first of the - * two training sequences - * @param flip user option to rotate the image(s) 180 degrees - * - */ - static sptr - make (const char *filename_png, size_t width, size_t height, - bool sync, bool flip); - }; + /*! + * Accepts a stream of floats in the range [0,1] which + * correspond to one sample per symbol (pixel) and + * outputs a grayscale PNG image. The user can + * choose between deriving a single PNG file for each + * width x length pixels or two PNG files corresponding to + * each one of the two different spectrum images contained + * in a NOAA APT transmission. The notation 'left' and 'right' + * is with respect to the original image sent by the satellite. + * Further, this block performs normalization on the input + * float values based on the max and min values observed in the stream. + * Adding to that, the user has the option to synchronize to the first of the + * two training sequences used by the NOAA APT protocol so that + * the two images are displayed one next to the other. The user + * can also select to rotate the image 180 degrees in case the captured one + * is upside down. + * + * + * @param filename_png the base filename of the output PNG file(s) + * @param width the width of the image in the APT transmission + * @param height the height of the image in the APT transmission + * @param sync user option for synchronizing to the first of the + * two training sequences + * @param flip user option to rotate the image(s) 180 degrees + * + */ + static sptr + make(const char *filename_png, size_t width, size_t height, + bool sync, bool flip); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_NOAA_APT_SINK_H */ diff --git a/include/satnogs/ogg_encoder.h b/include/satnogs/ogg_encoder.h index 18bd62c..c2f1bc6 100644 --- a/include/satnogs/ogg_encoder.h +++ b/include/satnogs/ogg_encoder.h @@ -24,32 +24,29 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Ogg encoder and sink block - * \ingroup satnogs - * - */ - class SATNOGS_API ogg_encoder : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief Ogg encoder and sink block + * \ingroup satnogs + * + */ +class SATNOGS_API ogg_encoder : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * Ogg encoder and sink block. - * @param filename filename of the output file - * @param samp_rate the sampling rate - * @param quality the quality of the output file. [0.1 - 1.0] (worst - best) - */ - static sptr - make (char* filename, double samp_rate, float quality); - }; + /*! + * Ogg encoder and sink block. + * @param filename filename of the output file + * @param samp_rate the sampling rate + * @param quality the quality of the output file. [0.1 - 1.0] (worst - best) + */ + static sptr + make(char *filename, double samp_rate, float quality); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_OGG_ENCODER_H */ diff --git a/include/satnogs/ogg_source.h b/include/satnogs/ogg_source.h index 2b73fcc..a61f69f 100644 --- a/include/satnogs/ogg_source.h +++ b/include/satnogs/ogg_source.h @@ -24,38 +24,35 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief OGG source block. Reads a file with an OGG audio and - * convert it to float samples - * - * \ingroup satnogs - * - */ - class SATNOGS_API ogg_source : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief OGG source block. Reads a file with an OGG audio and + * convert it to float samples + * + * \ingroup satnogs + * + */ +class SATNOGS_API ogg_source : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * - * @param filename the OGG audio file path - * @param channels number of channels of the OGG stream. - * If the actual OGG stream contains a different number of channels - * than specified an exception is raised - * @param repeat if set to true, when EOF is reached the block - * will continue to output samples from the beginning of the OGG file. - */ - static sptr - make (const std::string& filename, int channels = 1, - bool repeat = false); - }; + /*! + * + * @param filename the OGG audio file path + * @param channels number of channels of the OGG stream. + * If the actual OGG stream contains a different number of channels + * than specified an exception is raised + * @param repeat if set to true, when EOF is reached the block + * will continue to output samples from the beginning of the OGG file. + */ + static sptr + make(const std::string &filename, int channels = 1, + bool repeat = false); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_OGG_SOURCE_H */ diff --git a/include/satnogs/qb50_deframer.h b/include/satnogs/qb50_deframer.h index 5a9bf3b..ea23476 100644 --- a/include/satnogs/qb50_deframer.h +++ b/include/satnogs/qb50_deframer.h @@ -24,33 +24,30 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Parses the received AX.25 and separates the - * telecommand and control frames from the WOD frames. - * \ingroup satnogs - * - */ - class SATNOGS_API qb50_deframer : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief Parses the received AX.25 and separates the + * telecommand and control frames from the WOD frames. + * \ingroup satnogs + * + */ +class SATNOGS_API qb50_deframer : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /*! - * \brief Parses the received AX.25 and separates the - * telecommand and control frames from the WOD frames. - * - * @param wod_ssid the SSID that separates the WOD frames from the others - */ - static sptr - make (uint8_t wod_ssid); - }; + /*! + * \brief Parses the received AX.25 and separates the + * telecommand and control frames from the WOD frames. + * + * @param wod_ssid the SSID that separates the WOD frames from the others + */ + static sptr + make(uint8_t wod_ssid); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_QB50_DEFRAMER_H */ diff --git a/include/satnogs/shift_reg.h b/include/satnogs/shift_reg.h index 22b716d..6be1a8a 100644 --- a/include/satnogs/shift_reg.h +++ b/include/satnogs/shift_reg.h @@ -25,20 +25,17 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief Implements a bit shift register * */ -class SATNOGS_API shift_reg -{ +class SATNOGS_API shift_reg { public: - shift_reg (size_t len); - ~shift_reg (); + shift_reg(size_t len); + ~shift_reg(); void reset(); @@ -56,24 +53,24 @@ public: count(); shift_reg - operator|(const shift_reg& rhs); + operator|(const shift_reg &rhs); shift_reg - operator&(const shift_reg& rhs); + operator&(const shift_reg &rhs); shift_reg - operator^(const shift_reg& rhs); + operator^(const shift_reg &rhs); - shift_reg& + shift_reg & operator>>=(bool bit); - bool& + bool & operator[](size_t pos); bool operator[](size_t pos) const; - shift_reg& + shift_reg & operator<<=(bool bit); void @@ -88,8 +85,8 @@ public: bool back(); - friend std::ostream& - operator<<(std::ostream& os, const shift_reg& reg); + friend std::ostream & + operator<<(std::ostream &os, const shift_reg ®); private: const size_t d_len; diff --git a/include/satnogs/tc_tm.h b/include/satnogs/tc_tm.h index 2d67b94..901361e 100644 --- a/include/satnogs/tc_tm.h +++ b/include/satnogs/tc_tm.h @@ -119,274 +119,269 @@ #define TURN_ON 1 #define RESET 2 -namespace gr +namespace gr { +namespace satnogs { +/*! + * \brief Telemetry and telecommands packet methods + * \ingroup satnogs + */ + +/*! + * Return status codes + */ +typedef enum { + R_OBC_PKT_ILLEGAL_APPID = 0, //!< R_OBC_PKT_ILLEGAL_APPID illegal application ID + R_OBC_PKT_INV_LEN = 1, //!< R_OBC_PKT_INV_LEN invalid length + R_OBC_PKT_INC_CRC = 2, //!< R_OBC_PKT_INC_CRC incorrect CRC + R_OBC_PKT_ILLEGAL_PKT_TP = 3, //!< R_OBC_PKT_ILLEGAL_PKT_TP + R_OBC_PKT_ILLEGAL_PKT_STP = 4, //!< R_OBC_PKT_ILLEGAL_PKT_STP + R_OBC_PKT_ILLEGAL_APP_DATA = 5, //!< R_OBC_PKT_ILLEGAL_APP_DATA + R_OBC_OK = 6, //!< R_OBC_OK All ok + R_OBC_ERROR = 7, //!< R_OBC_ERROR an error occured + R_OBC_EOT = 8, //!< R_OBC_EOT End-of-transfer +} OBC_ret_state_t; + +union _cnv { + uint32_t cnv32; + uint16_t cnv16[2]; + uint8_t cnv8[4]; +}; + +typedef struct { + /* packet id */ + uint8_t ver; /* 3 bits, should be equal to 0 */ + uint8_t data_field_hdr; /* 1 bit, data_field_hdr exists in data = 1 */ + uint16_t app_id; /* TM: app id = 0 for time packets, = 0xff for idle packets. */ + uint8_t type; /* 1 bit, tm = 0, tc = 1 */ + + /* packet sequence control */ + uint8_t seq_flags; /* 3 bits, definition in TC_SEQ_xPACKET */ + uint16_t seq_count; /* 14 bits, packet counter, should be unique for each app id */ + + uint16_t len; /* 16 bits, C = (Number of octets in packet data field) - 1 */ + + uint8_t ack; /* 4 bits, definition in TC_ACK_xxxx 0 if its a TM */ + uint8_t ser_type; /* 8 bit, service type */ + uint8_t ser_subtype; /* 8 bit, service subtype */ + + /*optional*/ + uint8_t pckt_sub_cnt; /* 8 bits*/ + uint16_t dest_id; + + uint8_t *data; /* variable data, this should be fixed array */ + uint8_t padding; /* x bits, padding for word alligment */ + + uint16_t crc; /* CRC or checksum, mission specific*/ +} tc_tm_pkt; + + +const uint8_t services_verification_TC_TM[MAX_SERVICES][MAX_SUBTYPES][2]; +const uint8_t app_id_verification[MAX_APP_ID]; +const uint8_t services_verification_OBC_TC[MAX_SERVICES][MAX_SUBTYPES]; + +extern OBC_ret_state_t +verification_pack_pkt_api(uint8_t *buf, tc_tm_pkt *pkt, + uint16_t *buf_pointer); +extern OBC_ret_state_t +hk_pack_pkt_api(uint8_t *buf, tc_tm_pkt *pkt, uint16_t *buf_pointer); + + +static inline uint8_t +ecss_tm_checksum(const uint8_t *data, uint16_t size) { - namespace satnogs - { - /*! - * \brief Telemetry and telecommands packet methods - * \ingroup satnogs - */ + uint8_t CRC = 0; + for (int i = 0; i <= size; i++) { + CRC = CRC ^ data[i]; + } + return CRC; +} - /*! - * Return status codes - */ - typedef enum - { - R_OBC_PKT_ILLEGAL_APPID = 0, //!< R_OBC_PKT_ILLEGAL_APPID illegal application ID - R_OBC_PKT_INV_LEN = 1, //!< R_OBC_PKT_INV_LEN invalid length - R_OBC_PKT_INC_CRC = 2, //!< R_OBC_PKT_INC_CRC incorrect CRC - R_OBC_PKT_ILLEGAL_PKT_TP = 3, //!< R_OBC_PKT_ILLEGAL_PKT_TP - R_OBC_PKT_ILLEGAL_PKT_STP = 4, //!< R_OBC_PKT_ILLEGAL_PKT_STP - R_OBC_PKT_ILLEGAL_APP_DATA = 5, //!< R_OBC_PKT_ILLEGAL_APP_DATA - R_OBC_OK = 6, //!< R_OBC_OK All ok - R_OBC_ERROR = 7, //!< R_OBC_ERROR an error occured - R_OBC_EOT = 8, //!< R_OBC_EOT End-of-transfer - } OBC_ret_state_t; +/*Must check for endianess*/ +static inline OBC_ret_state_t +ecss_tm_unpack_pkt(const uint8_t *buf, tc_tm_pkt *pkt, const uint16_t size) +{ + union _cnv cnv; + uint8_t tmp_crc[2]; - union _cnv - { - uint32_t cnv32; - uint16_t cnv16[2]; - uint8_t cnv8[4]; - }; + uint8_t ver, dfield_hdr, ccsds_sec_hdr, tc_pus; - typedef struct - { - /* packet id */ - uint8_t ver; /* 3 bits, should be equal to 0 */ - uint8_t data_field_hdr; /* 1 bit, data_field_hdr exists in data = 1 */ - uint16_t app_id; /* TM: app id = 0 for time packets, = 0xff for idle packets. */ - uint8_t type; /* 1 bit, tm = 0, tc = 1 */ + tmp_crc[0] = buf[size - 1]; + tmp_crc[1] = ecss_tm_checksum(buf, size - 2); - /* packet sequence control */ - uint8_t seq_flags; /* 3 bits, definition in TC_SEQ_xPACKET */ - uint16_t seq_count; /* 14 bits, packet counter, should be unique for each app id */ + ver = buf[0] >> 5; - uint16_t len; /* 16 bits, C = (Number of octets in packet data field) - 1 */ + pkt->type = (buf[0] >> 4) & 0x01; + dfield_hdr = (buf[0] >> 3) & 0x01; - uint8_t ack; /* 4 bits, definition in TC_ACK_xxxx 0 if its a TM */ - uint8_t ser_type; /* 8 bit, service type */ - uint8_t ser_subtype; /* 8 bit, service subtype */ + cnv.cnv8[0] = buf[1]; + cnv.cnv8[1] = 0x07 & buf[0]; + pkt->app_id = cnv.cnv16[0]; - /*optional*/ - uint8_t pckt_sub_cnt; /* 8 bits*/ - uint16_t dest_id; + pkt->seq_flags = buf[2] >> 6; - uint8_t *data; /* variable data, this should be fixed array */ - uint8_t padding; /* x bits, padding for word alligment */ + cnv.cnv8[0] = buf[3]; + cnv.cnv8[1] = buf[2] & 0x3F; + pkt->seq_count = cnv.cnv16[0]; - uint16_t crc; /* CRC or checksum, mission specific*/ - } tc_tm_pkt; + cnv.cnv8[0] = buf[4]; + cnv.cnv8[1] = buf[5]; + pkt->len = cnv.cnv16[0]; + ccsds_sec_hdr = buf[6] >> 7; - const uint8_t services_verification_TC_TM[MAX_SERVICES][MAX_SUBTYPES][2]; - const uint8_t app_id_verification[MAX_APP_ID]; - const uint8_t services_verification_OBC_TC[MAX_SERVICES][MAX_SUBTYPES]; + tc_pus = buf[6] >> 4; - extern OBC_ret_state_t - verification_pack_pkt_api (uint8_t *buf, tc_tm_pkt *pkt, - uint16_t *buf_pointer); - extern OBC_ret_state_t - hk_pack_pkt_api (uint8_t *buf, tc_tm_pkt *pkt, uint16_t *buf_pointer); + pkt->ack = 0x04 & buf[6]; + pkt->ser_type = buf[7]; + pkt->ser_subtype = buf[8]; + pkt->dest_id = buf[9]; - static inline uint8_t - ecss_tm_checksum (const uint8_t *data, uint16_t size) - { - uint8_t CRC = 0; - for (int i = 0; i <= size; i++) { - CRC = CRC ^ data[i]; - } - return CRC; - } + if (app_id_verification[pkt->app_id] != 1) { + return R_OBC_PKT_ILLEGAL_APPID; + } - /*Must check for endianess*/ - static inline OBC_ret_state_t - ecss_tm_unpack_pkt (const uint8_t *buf, tc_tm_pkt *pkt, const uint16_t size) - { - union _cnv cnv; - uint8_t tmp_crc[2]; + if (pkt->len != size - 7) { + return R_OBC_PKT_INV_LEN; + } - uint8_t ver, dfield_hdr, ccsds_sec_hdr, tc_pus; + if (tmp_crc[0] != tmp_crc[1]) { + return R_OBC_PKT_INC_CRC; + } - tmp_crc[0] = buf[size - 1]; - tmp_crc[1] = ecss_tm_checksum (buf, size - 2); + if (services_verification_TC_TM[pkt->ser_type][pkt->ser_subtype][pkt->type] + != 1) { + return R_OBC_PKT_ILLEGAL_PKT_TP; + } - ver = buf[0] >> 5; + if (ver != 0) { + return R_OBC_ERROR; + } - pkt->type = (buf[0] >> 4) & 0x01; - dfield_hdr = (buf[0] >> 3) & 0x01; + if (tc_pus != 1) { + return R_OBC_ERROR; + } - cnv.cnv8[0] = buf[1]; - cnv.cnv8[1] = 0x07 & buf[0]; - pkt->app_id = cnv.cnv16[0]; + if (ccsds_sec_hdr != 0) { + return R_OBC_ERROR; + } - pkt->seq_flags = buf[2] >> 6; + if (pkt->type != TC && pkt->type != TM) { + return R_OBC_ERROR; + } - cnv.cnv8[0] = buf[3]; - cnv.cnv8[1] = buf[2] & 0x3F; - pkt->seq_count = cnv.cnv16[0]; + if (dfield_hdr != 1) { + return R_OBC_ERROR; + } - cnv.cnv8[0] = buf[4]; - cnv.cnv8[1] = buf[5]; - pkt->len = cnv.cnv16[0]; + if (pkt->ack != TC_ACK_NO || pkt->ack != TC_ACK_ACC + || pkt->ack != TC_ACK_EXE_COMP) { + return R_OBC_ERROR; + } - ccsds_sec_hdr = buf[6] >> 7; + for (int i = 0; i < pkt->len - 4; i++) { + pkt->data[i] = buf[10 + i]; + } - tc_pus = buf[6] >> 4; + return R_OBC_OK; +} - pkt->ack = 0x04 & buf[6]; +/** + * Packs a TC packet into a byte buffer + * @param buf buffer to store the data to be sent + * @param pkt the data to be stored in the buffer + * @param size size of the array + * @return appropriate error code or R_OBC_OK if all operation succeed + */ +static inline OBC_ret_state_t +ecss_tm_pack_pkt(uint8_t *buf, tc_tm_pkt *pkt, uint16_t *size) +{ - pkt->ser_type = buf[7]; - pkt->ser_subtype = buf[8]; - pkt->dest_id = buf[9]; + union _cnv cnv; + uint8_t buf_pointer; - if (app_id_verification[pkt->app_id] != 1) { - return R_OBC_PKT_ILLEGAL_APPID; - } + cnv.cnv16[0] = pkt->app_id; - if (pkt->len != size - 7) { - return R_OBC_PKT_INV_LEN; - } + buf[0] = (ECSS_VER_NUMBER << 5 | pkt->type << 4 + | ECSS_DATA_FIELD_HDR_FLG << 3 | cnv.cnv8[1]); + buf[1] = cnv.cnv8[0]; - if (tmp_crc[0] != tmp_crc[1]) { - return R_OBC_PKT_INC_CRC; - } + cnv.cnv16[0] = pkt->seq_count; + buf[2] = (pkt->seq_flags << 6 | cnv.cnv8[1]); + buf[3] = cnv.cnv8[0]; - if (services_verification_TC_TM[pkt->ser_type][pkt->ser_subtype][pkt->type] - != 1) { - return R_OBC_PKT_ILLEGAL_PKT_TP; - } + /* TYPE = 0 TM, TYPE = 1 TC*/ + if (pkt->type == TM) { + buf[6] = ECSS_PUS_VER << 4; + } + else if (pkt->type == TC) { + buf[6] = (ECSS_SEC_HDR_FIELD_FLG << 7 | ECSS_PUS_VER << 4 | pkt->ack); + } + else { + return R_OBC_ERROR; + } - if (ver != 0) { - return R_OBC_ERROR; - } + buf[7] = pkt->ser_type; + buf[8] = pkt->ser_subtype; + buf[9] = pkt->dest_id; /*source or destination*/ - if (tc_pus != 1) { - return R_OBC_ERROR; - } + buf_pointer = 10; - if (ccsds_sec_hdr != 0) { - return R_OBC_ERROR; - } + if (pkt->ser_type == TC_VERIFICATION_SERVICE) { + //cnv.cnv16[0] = tc_pkt_id; + //cnv.cnv16[1] = tc_pkt_seq_ctrl; - if (pkt->type != TC && pkt->type != TM) { - return R_OBC_ERROR; - } + /*verification_pack_pkt_api (buf, pkt, &buf_pointer);*/ - if (dfield_hdr != 1) { - return R_OBC_ERROR; - } + } + else if (pkt->ser_type == TC_HOUSEKEEPING_SERVICE) { - if (pkt->ack != TC_ACK_NO || pkt->ack != TC_ACK_ACC - || pkt->ack != TC_ACK_EXE_COMP) { - return R_OBC_ERROR; - } + /*hk_pack_pkt_api (buf, pkt, &buf_pointer);*/ - for (int i = 0; i < pkt->len - 4; i++) { - pkt->data[i] = buf[10 + i]; - } + } + else if (pkt->ser_type == TC_FUNCTION_MANAGEMENT_SERVICE + && pkt->ser_subtype == 1) { - return R_OBC_OK; - } + buf[10] = pkt->data[0]; - /** - * Packs a TC packet into a byte buffer - * @param buf buffer to store the data to be sent - * @param pkt the data to be stored in the buffer - * @param size size of the array - * @return appropriate error code or R_OBC_OK if all operation succeed - */ - static inline OBC_ret_state_t - ecss_tm_pack_pkt (uint8_t *buf, tc_tm_pkt *pkt, uint16_t *size) - { + buf[11] = pkt->data[1]; + buf[12] = pkt->data[2]; + buf[13] = pkt->data[3]; + buf[14] = pkt->data[4]; - union _cnv cnv; - uint8_t buf_pointer; + buf_pointer += 5; - cnv.cnv16[0] = pkt->app_id; + } + else { + return R_OBC_ERROR; + } - buf[0] = ( ECSS_VER_NUMBER << 5 | pkt->type << 4 - | ECSS_DATA_FIELD_HDR_FLG << 3 | cnv.cnv8[1]); - buf[1] = cnv.cnv8[0]; + /*check if this is correct*/ + cnv.cnv16[0] = buf_pointer - 6; + buf[4] = cnv.cnv8[0]; + buf[5] = cnv.cnv8[1]; - cnv.cnv16[0] = pkt->seq_count; - buf[2] = (pkt->seq_flags << 6 | cnv.cnv8[1]); - buf[3] = cnv.cnv8[0]; + buf[buf_pointer] = ecss_tm_checksum(buf, buf_pointer - 1); + *size = buf_pointer; + return R_OBC_OK; +} - /* TYPE = 0 TM, TYPE = 1 TC*/ - if (pkt->type == TM) { - buf[6] = ECSS_PUS_VER << 4; - } - else if (pkt->type == TC) { - buf[6] = ( ECSS_SEC_HDR_FIELD_FLG << 7 | ECSS_PUS_VER << 4 | pkt->ack); - } - else { - return R_OBC_ERROR; - } +static inline OBC_ret_state_t +ecss_tm_crt_pkt(tc_tm_pkt *pkt, uint16_t app_id, uint8_t type, uint8_t ack, + uint8_t ser_type, uint8_t ser_subtype, uint16_t dest_id) +{ - buf[7] = pkt->ser_type; - buf[8] = pkt->ser_subtype; - buf[9] = pkt->dest_id; /*source or destination*/ + pkt->type = type; + pkt->app_id = app_id; + pkt->dest_id = dest_id; - buf_pointer = 10; + pkt->ser_type = ser_type; + pkt->ser_subtype = ser_subtype; - if (pkt->ser_type == TC_VERIFICATION_SERVICE) { - //cnv.cnv16[0] = tc_pkt_id; - //cnv.cnv16[1] = tc_pkt_seq_ctrl; + return R_OBC_OK; +} - /*verification_pack_pkt_api (buf, pkt, &buf_pointer);*/ - - } - else if (pkt->ser_type == TC_HOUSEKEEPING_SERVICE) { - - /*hk_pack_pkt_api (buf, pkt, &buf_pointer);*/ - - } - else if (pkt->ser_type == TC_FUNCTION_MANAGEMENT_SERVICE - && pkt->ser_subtype == 1) { - - buf[10] = pkt->data[0]; - - buf[11] = pkt->data[1]; - buf[12] = pkt->data[2]; - buf[13] = pkt->data[3]; - buf[14] = pkt->data[4]; - - buf_pointer += 5; - - } - else { - return R_OBC_ERROR; - } - - /*check if this is correct*/ - cnv.cnv16[0] = buf_pointer - 6; - buf[4] = cnv.cnv8[0]; - buf[5] = cnv.cnv8[1]; - - buf[buf_pointer] = ecss_tm_checksum (buf, buf_pointer - 1); - *size = buf_pointer; - return R_OBC_OK; - } - - static inline OBC_ret_state_t - ecss_tm_crt_pkt (tc_tm_pkt *pkt, uint16_t app_id, uint8_t type, uint8_t ack, - uint8_t ser_type, uint8_t ser_subtype, uint16_t dest_id) - { - - pkt->type = type; - pkt->app_id = app_id; - pkt->dest_id = dest_id; - - pkt->ser_type = ser_type; - pkt->ser_subtype = ser_subtype; - - return R_OBC_OK; - } - - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_TC_TM_H */ diff --git a/include/satnogs/tcp_rigctl_msg_source.h b/include/satnogs/tcp_rigctl_msg_source.h index d8db43b..28691a7 100644 --- a/include/satnogs/tcp_rigctl_msg_source.h +++ b/include/satnogs/tcp_rigctl_msg_source.h @@ -24,42 +24,39 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief Block that accepts TCP messages with rigctl commands. Depending - * the command contents this block produces an appropriate PMT message - * to control other blocks in the flowgraph - * \ingroup satnogs - * - */ - class SATNOGS_API tcp_rigctl_msg_source : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief Block that accepts TCP messages with rigctl commands. Depending + * the command contents this block produces an appropriate PMT message + * to control other blocks in the flowgraph + * \ingroup satnogs + * + */ +class SATNOGS_API tcp_rigctl_msg_source : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /** - * Rigctl TCP command accepter - * - * @param addr the address of the interface to listen at - * @param port the TCP port to listen or connect - * @param server_mode If set to yes this block, act as a rigctl server. - * Otherwise as a rigctl client - * @param interval_ms The interval in milliseconds at which the client - * request the frequency from the rigctl - * @param mtu the maximum MTU - * @return shared pointer of the block - */ - static sptr - make (const std::string& addr, uint16_t port, bool server_mode, - size_t interval_ms = 1000, size_t mtu = 1500); - }; + /** + * Rigctl TCP command accepter + * + * @param addr the address of the interface to listen at + * @param port the TCP port to listen or connect + * @param server_mode If set to yes this block, act as a rigctl server. + * Otherwise as a rigctl client + * @param interval_ms The interval in milliseconds at which the client + * request the frequency from the rigctl + * @param mtu the maximum MTU + * @return shared pointer of the block + */ + static sptr + make(const std::string &addr, uint16_t port, bool server_mode, + size_t interval_ms = 1000, size_t mtu = 1500); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_TCP_RIGCTL_MSG_SOURCE_H */ diff --git a/include/satnogs/udp_msg_sink.h b/include/satnogs/udp_msg_sink.h index 30d61ae..5d553ac 100644 --- a/include/satnogs/udp_msg_sink.h +++ b/include/satnogs/udp_msg_sink.h @@ -25,29 +25,28 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - /*! - * \brief <+description of block+> - * \ingroup satnogs - * - */ - class SATNOGS_API udp_msg_sink : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief <+description of block+> + * \ingroup satnogs + * + */ +class SATNOGS_API udp_msg_sink : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /** - * UDP sink that accepts PMT messages - * @param addr the address of the destination host - * @param port the destination UDP port - * @param mtu the maximum MTU - */ - static sptr make(const std::string& addr, uint16_t port, size_t mtu); - }; + /** + * UDP sink that accepts PMT messages + * @param addr the address of the destination host + * @param port the destination UDP port + * @param mtu the maximum MTU + */ + static sptr make(const std::string &addr, uint16_t port, size_t mtu); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_UDP_MSG_SINK_H */ diff --git a/include/satnogs/udp_msg_source.h b/include/satnogs/udp_msg_source.h index ad6b45e..a46fa37 100644 --- a/include/satnogs/udp_msg_source.h +++ b/include/satnogs/udp_msg_source.h @@ -24,39 +24,36 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief UDP message/command accepter. - * - * This block received UDP messages from localhost or other network hosts - * and produces PMT messages. - * - * \ingroup satnogs - * - */ - class SATNOGS_API udp_msg_source : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief UDP message/command accepter. + * + * This block received UDP messages from localhost or other network hosts + * and produces PMT messages. + * + * \ingroup satnogs + * + */ +class SATNOGS_API udp_msg_source : virtual public gr::block { +public: + typedef boost::shared_ptr sptr; - /** - * Creates a UDP message accepter block - * @param addr the address to bind the UDP socket - * @param port the UDP port to wait for packets - * @param mtu the maximum MTU. Used to pre-allocate a maximum packet size - * @param type code of the data type of each message. 0 corresponds to raw - * bytes, 1 to 32-bit signed integers and 2 to 3 bit unsigned integers. - */ - static sptr - make (const std::string& addr, uint16_t port, size_t mtu = 1500, - size_t type = 0); - }; + /** + * Creates a UDP message accepter block + * @param addr the address to bind the UDP socket + * @param port the UDP port to wait for packets + * @param mtu the maximum MTU. Used to pre-allocate a maximum packet size + * @param type code of the data type of each message. 0 corresponds to raw + * bytes, 1 to 32-bit signed integers and 2 to 3 bit unsigned integers. + */ + static sptr + make(const std::string &addr, uint16_t port, size_t mtu = 1500, + size_t type = 0); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_UDP_MSG_SOURCE_H */ diff --git a/include/satnogs/upsat_fsk_frame_encoder.h b/include/satnogs/upsat_fsk_frame_encoder.h index 5b3df9f..b8c6db5 100644 --- a/include/satnogs/upsat_fsk_frame_encoder.h +++ b/include/satnogs/upsat_fsk_frame_encoder.h @@ -24,75 +24,72 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief This block implements a FSK frame encoder for the UPSAT satellite. - * It takes as input a message containing the PDU and performs the NRZ - * encoding. The resulting float samples can be passed from a FM modulation - * block and then to the SDR device. - * - * \ingroup satnogs - * - */ - class SATNOGS_API upsat_fsk_frame_encoder : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief This block implements a FSK frame encoder for the UPSAT satellite. + * It takes as input a message containing the PDU and performs the NRZ + * encoding. The resulting float samples can be passed from a FM modulation + * block and then to the SDR device. + * + * \ingroup satnogs + * + */ +class SATNOGS_API upsat_fsk_frame_encoder : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /*! - * Creates an FSK encoding block. Note that this block does NOT perform - * the frequency modulation. You can use the existing frequency modulation - * block shipped with the GNU Radio. - * - * @param preamble the bytes that consist the preamble of the frame - * - * @param sync_word the byte synchronization word - * - * @param append_crc if set to true the encoder will append a two byte - * CRC field at the end of the frame. The CRC algorithm is compatible - * with the CC1120 chip. - * - * @param whitening true if the transmitted data have been processed by - * the whitening algorithm of the CC1120 chip. False otherwise. - * - * @param manchester true if the transmitted data have been processed by - * the Manchester algorithm of the CC1120 chip. False otherwise. - * - * @param msb_first if set to true, the the treansmission starts from the - * MSB of each byte. In case the AX.25 encapuslation is selected, this - * parameter is NOT taken into consideration for the AX.25 part, - * as the AX.25 dictates that the LS bit should be sent first. - * - * @param ax25_format if set to true the frame payload will be encoded - * using AX.25 encapsulation. - * - * @param settling_samples the number of zero samples that the encoder - * should append after the end of the FSK frame. This is especially - * important when an arbitrary in-out ratio resampler is used. The - * arbitrary in-out ratio of samples will cause the stream tags to be - * delivered at the sink block out-of-sync causing the frame transmission - * to terminate sooner. - * - * @param ax25_dest_addr the destination AX.25 address - * @param ax25_dest_ssid the destination AX.25 SSID - * @param ax25_src_addr the source AX.25 address - * @param ax25_src_ssid the source AX.25 SSID - * - */ - static sptr - make (const std::vector& preamble, - const std::vector& sync_word, bool append_crc, - bool whitening, bool manchester, bool msb_first, bool ax25_format, - const std::string& ax25_dest_addr, uint8_t ax25_dest_ssid, - const std::string& ax25_src_addr, uint8_t ax25_src_ssid, - size_t settling_samples); - }; + /*! + * Creates an FSK encoding block. Note that this block does NOT perform + * the frequency modulation. You can use the existing frequency modulation + * block shipped with the GNU Radio. + * + * @param preamble the bytes that consist the preamble of the frame + * + * @param sync_word the byte synchronization word + * + * @param append_crc if set to true the encoder will append a two byte + * CRC field at the end of the frame. The CRC algorithm is compatible + * with the CC1120 chip. + * + * @param whitening true if the transmitted data have been processed by + * the whitening algorithm of the CC1120 chip. False otherwise. + * + * @param manchester true if the transmitted data have been processed by + * the Manchester algorithm of the CC1120 chip. False otherwise. + * + * @param msb_first if set to true, the the treansmission starts from the + * MSB of each byte. In case the AX.25 encapuslation is selected, this + * parameter is NOT taken into consideration for the AX.25 part, + * as the AX.25 dictates that the LS bit should be sent first. + * + * @param ax25_format if set to true the frame payload will be encoded + * using AX.25 encapsulation. + * + * @param settling_samples the number of zero samples that the encoder + * should append after the end of the FSK frame. This is especially + * important when an arbitrary in-out ratio resampler is used. The + * arbitrary in-out ratio of samples will cause the stream tags to be + * delivered at the sink block out-of-sync causing the frame transmission + * to terminate sooner. + * + * @param ax25_dest_addr the destination AX.25 address + * @param ax25_dest_ssid the destination AX.25 SSID + * @param ax25_src_addr the source AX.25 address + * @param ax25_src_ssid the source AX.25 SSID + * + */ + static sptr + make(const std::vector &preamble, + const std::vector &sync_word, bool append_crc, + bool whitening, bool manchester, bool msb_first, bool ax25_format, + const std::string &ax25_dest_addr, uint8_t ax25_dest_ssid, + const std::string &ax25_src_addr, uint8_t ax25_src_ssid, + size_t settling_samples); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_UPSAT_FSK_FRAME_ENCODER_H */ diff --git a/include/satnogs/utils.h b/include/satnogs/utils.h index 2d42795..c143ee2 100644 --- a/include/satnogs/utils.h +++ b/include/satnogs/utils.h @@ -25,11 +25,9 @@ #include #include -namespace gr -{ +namespace gr { -namespace satnogs -{ +namespace satnogs { #define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) @@ -40,16 +38,16 @@ namespace satnogs * @return the mean absolute percentage error */ static inline double -mape (double ref, double estimation) +mape(double ref, double estimation) { - return std::abs (ref - estimation) / ref; + return std::abs(ref - estimation) / ref; } /** * Counts the number of active bits in x */ static inline unsigned int -bit_count (unsigned int x) +bit_count(unsigned int x) { /* * Some more magic from @@ -60,53 +58,54 @@ bit_count (unsigned int x) return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; } -static const uint8_t _bytes_reversed[256] = - { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, - 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, - 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, - 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, - 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, - 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, - 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, - 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, - 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, - 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, - 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, - 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, - 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, - 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, - 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, - 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, - 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, - 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, - 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, - 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, - 0x7F, 0xFF }; +static const uint8_t _bytes_reversed[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, + 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, + 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, + 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, + 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, + 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, + 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, + 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, + 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, + 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, + 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, + 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, + 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, + 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, + 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, + 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, + 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, + 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, + 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, + 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, + 0x7F, 0xFF +}; /** * Reverse the bits of the byte b. * @param b the byte to be mirrored. */ static inline uint8_t -reverse_byte (uint8_t b) +reverse_byte(uint8_t b) { return _bytes_reversed[b]; } static inline uint32_t -reverse_uint32_bytes (uint32_t i) +reverse_uint32_bytes(uint32_t i) { return (_bytes_reversed[i & 0xff] << 24) - | (_bytes_reversed[(i >> 8) & 0xff] << 16) - | (_bytes_reversed[(i >> 16) & 0xff] << 8) - | (_bytes_reversed[(i >> 24) & 0xff]); + | (_bytes_reversed[(i >> 8) & 0xff] << 16) + | (_bytes_reversed[(i >> 16) & 0xff] << 8) + | (_bytes_reversed[(i >> 24) & 0xff]); } static inline uint64_t -reverse_uint64_bytes (uint64_t x) +reverse_uint64_bytes(uint64_t x) { x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; @@ -124,61 +123,62 @@ reverse_uint64_bytes (uint64_t x) * @return the CRC-32 result */ static inline uint32_t -update_crc32 (uint32_t crc, const uint8_t *data, size_t len) +update_crc32(uint32_t crc, const uint8_t *data, size_t len) { - static const uint32_t crc32_lut[256] = - { 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, - 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 0x79DCB8A4L, - 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, - 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, - 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, - 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, - 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, - 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, - 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, - 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x26D930ACL, 0x51DE003AL, - 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, - 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, - 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 0x76DC4190L, - 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, - 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, - 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, - 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, - 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, - 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, - 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, - 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, - 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, - 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 0xBE0B1010L, - 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, - 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, - 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 0x9ABFB3B6L, - 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, - 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, - 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 0xF00F9344L, - 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, - 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, - 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, - 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, - 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, - 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, - 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, - 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, - 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, - 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, - 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, - 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, - 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, - 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, - 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, - 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, - 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, - 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, - 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, - 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, - 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, - 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, - 0x2D02EF8DL }; + static const uint32_t crc32_lut[256] = { + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, + 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 0x79DCB8A4L, + 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, + 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, + 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, + 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, + 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, + 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, + 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, + 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x26D930ACL, 0x51DE003AL, + 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, + 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, + 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 0x76DC4190L, + 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, + 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, + 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, + 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, + 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, + 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, + 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, + 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, + 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, + 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 0xBE0B1010L, + 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, + 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, + 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 0x9ABFB3B6L, + 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, + 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, + 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 0xF00F9344L, + 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, + 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, + 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, + 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, + 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, + 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, + 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, + 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, + 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, + 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, + 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, + 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, + 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, + 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, + 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, + 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, + 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, + 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, + 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, + 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, + 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, + 0x2D02EF8DL + }; register uint32_t i; for (i = 0; i < len; i++) { @@ -194,9 +194,9 @@ update_crc32 (uint32_t crc, const uint8_t *data, size_t len) * @return the CRC-32 of the buffer */ static inline uint32_t -crc32 (const uint8_t *buf, size_t len) +crc32(const uint8_t *buf, size_t len) { - unsigned int crc = update_crc32 (0xffffffff, buf, len) ^ 0xffffffff; + unsigned int crc = update_crc32(0xffffffff, buf, len) ^ 0xffffffff; return crc; } diff --git a/include/satnogs/waterfall_sink.h b/include/satnogs/waterfall_sink.h index ee0d654..e946ae0 100644 --- a/include/satnogs/waterfall_sink.h +++ b/include/satnogs/waterfall_sink.h @@ -24,53 +24,50 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - /*! - * \brief This block computes the waterfall of the incoming signal - * and stores the result to a file. - * - * The file has a special header, so that the satnogs_waterfall Gnuplot - * script to be able to plot it properly. - * - * \ingroup satnogs - * - */ - class SATNOGS_API waterfall_sink : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; +/*! + * \brief This block computes the waterfall of the incoming signal + * and stores the result to a file. + * + * The file has a special header, so that the satnogs_waterfall Gnuplot + * script to be able to plot it properly. + * + * \ingroup satnogs + * + */ +class SATNOGS_API waterfall_sink : virtual public gr::sync_block { +public: + typedef boost::shared_ptr sptr; - /** - * This block computes the waterfall of the incoming signal - * and stores the result to a file. - * - * The file has a special header, so that the satnogs_waterfall Gnuplot - * script to be able to plot it properly. - * - * @param samp_rate the sampling rate - * @param center_freq the observation center frequency. Used only for - * plotting reasons. For a normalized frequency x-axis set it to 0. - * @param pps pixels per second - * @param fft_size FFT size - * @param filename the name of the output file - * @param mode the mode that the waterfall. - * - 0: Simple decimation - * - 1: Max hold - * - 2: Mean energy - * - * @return shared pointer to the object - */ - static sptr - make (double samp_rate, double center_freq, - double pps, size_t fft_size, - const std::string& filename, int mode = 0); - }; + /** + * This block computes the waterfall of the incoming signal + * and stores the result to a file. + * + * The file has a special header, so that the satnogs_waterfall Gnuplot + * script to be able to plot it properly. + * + * @param samp_rate the sampling rate + * @param center_freq the observation center frequency. Used only for + * plotting reasons. For a normalized frequency x-axis set it to 0. + * @param pps pixels per second + * @param fft_size FFT size + * @param filename the name of the output file + * @param mode the mode that the waterfall. + * - 0: Simple decimation + * - 1: Max hold + * - 2: Mean energy + * + * @return shared pointer to the object + */ + static sptr + make(double samp_rate, double center_freq, + double pps, size_t fft_size, + const std::string &filename, int mode = 0); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_WATERFALL_SINK_H */ diff --git a/include/satnogs/whitening.h b/include/satnogs/whitening.h index 9d34a74..9657b27 100644 --- a/include/satnogs/whitening.h +++ b/include/satnogs/whitening.h @@ -25,45 +25,42 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /*! * \brief Performs data whitening and de-whitening * */ -class SATNOGS_API whitening -{ +class SATNOGS_API whitening { public: static int base_unique_id; int - unique_id (); + unique_id(); typedef boost::shared_ptr whitening_sptr; static whitening_sptr make(uint32_t mask, uint32_t seed, uint32_t order); - whitening (uint32_t mask, uint32_t seed, uint32_t order); + whitening(uint32_t mask, uint32_t seed, uint32_t order); ~whitening(); void - reset (); + reset(); void - scramble (uint8_t *out, const uint8_t *in, size_t len, bool msb = false); + scramble(uint8_t *out, const uint8_t *in, size_t len, bool msb = false); void - descramble (uint8_t *out, const uint8_t *in, size_t len, bool msb = false); + descramble(uint8_t *out, const uint8_t *in, size_t len, bool msb = false); void - scramble_one_bit_per_byte (uint8_t *out, const uint8_t *in, size_t bits_num); + scramble_one_bit_per_byte(uint8_t *out, const uint8_t *in, size_t bits_num); void - descramble_one_bit_per_byte (uint8_t *out, const uint8_t *in, - size_t bits_num); + descramble_one_bit_per_byte(uint8_t *out, const uint8_t *in, + size_t bits_num); private: digital::lfsr d_lfsr; diff --git a/lib/amsat_duv_decoder.cc b/lib/amsat_duv_decoder.cc index 10446e8..6626ebe 100644 --- a/lib/amsat_duv_decoder.cc +++ b/lib/amsat_duv_decoder.cc @@ -31,10 +31,8 @@ extern "C" { #include } -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /** * Actual frame size without RS padding and parity. @@ -42,14 +40,13 @@ namespace satnogs */ const size_t amsat_duv_decoder::amsat_fox_duv_frame_size = 6 + 58; -const uint8_t amsat_duv_decoder::amsat_fox_spacecraft_id[] - { - 0x1 /* FOX-1A */, - 0x2 /* FOX-1B */, - 0x3 /* FOX-1C */, - 0x4 /* FOX-1D */, - 0x5 /* FOX-1E */ - }; +const uint8_t amsat_duv_decoder::amsat_fox_spacecraft_id[] { + 0x1 /* FOX-1A */, + 0x2 /* FOX-1B */, + 0x3 /* FOX-1C */, + 0x4 /* FOX-1D */, + 0x5 /* FOX-1E */ +}; /** * Creates a shared pointer to a amsat_duv_decoder object @@ -58,11 +55,11 @@ const uint8_t amsat_duv_decoder::amsat_fox_spacecraft_id[] * @return a shared pointer to a amsat_duv_decoder object */ decoder::decoder_sptr -amsat_duv_decoder::make (const std::string &control_symbol, - size_t max_frame_len) +amsat_duv_decoder::make(const std::string &control_symbol, + size_t max_frame_len) { - return decoder::decoder_sptr ( - new amsat_duv_decoder (control_symbol, max_frame_len)); + return decoder::decoder_sptr( + new amsat_duv_decoder(control_symbol, max_frame_len)); } /** @@ -71,33 +68,33 @@ amsat_duv_decoder::make (const std::string &control_symbol, * @param control_symbol the control symbol indicating the start of a frame * @param max_frame_len the maximum frame length */ -amsat_duv_decoder::amsat_duv_decoder (const std::string &control_symbol, - size_t max_frame_len) : - decoder (1, max_frame_len), - d_erasure_cnt (0), - d_control_symbol_pos (0), - d_control_symbol_neg (0), - d_data_reg (0), - d_wrong_bits (0), - d_wrong_bits_neg (0), - d_nwrong (0), - d_nwrong_neg (0), - d_word_cnt (0), - d_bitstream_idx (0), - d_state (SEARCH_SYNC) +amsat_duv_decoder::amsat_duv_decoder(const std::string &control_symbol, + size_t max_frame_len) : + decoder(1, max_frame_len), + d_erasure_cnt(0), + d_control_symbol_pos(0), + d_control_symbol_neg(0), + d_data_reg(0), + d_wrong_bits(0), + d_wrong_bits_neg(0), + d_nwrong(0), + d_nwrong_neg(0), + d_word_cnt(0), + d_bitstream_idx(0), + d_state(SEARCH_SYNC) { d_8b_words = new uint8_t[max_frame_len]; d_erasures_indexes = new int[max_frame_len]; - if (!set_access_code (control_symbol)) { - throw std::out_of_range ("control_symbol is not 10 bits"); + if (!set_access_code(control_symbol)) { + throw std::out_of_range("control_symbol is not 10 bits"); } } bool -amsat_duv_decoder::set_access_code (const std::string &control_symbol) +amsat_duv_decoder::set_access_code(const std::string &control_symbol) { - unsigned len = control_symbol.length (); // # of bytes in string + unsigned len = control_symbol.length(); // # of bytes in string /* if the control sequence is not 10-bit then throw exception */ if (len != 10) { @@ -106,20 +103,20 @@ amsat_duv_decoder::set_access_code (const std::string &control_symbol) for (size_t i = 0; i < len; i++) { d_control_symbol_pos = (d_control_symbol_pos << 1) - | (control_symbol[i] & 0x1); + | (control_symbol[i] & 0x1); } d_control_symbol_neg = (~d_control_symbol_pos) & 0x3FF; return true; } -amsat_duv_decoder::~amsat_duv_decoder () +amsat_duv_decoder::~amsat_duv_decoder() { delete[] d_8b_words; delete[] d_erasures_indexes; } void -amsat_duv_decoder::process_10b (uint16_t word, size_t write_pos) +amsat_duv_decoder::process_10b(uint16_t word, size_t write_pos) { uint16_t diff_bits = 0; uint8_t min_pos = 0; @@ -131,7 +128,7 @@ amsat_duv_decoder::process_10b (uint16_t word, size_t write_pos) while ((i < 256) && (min_dist > 0)) { diff_bits = (word ^ (d_lookup_8b10b[0][i])) & 0x3FF; - curr_dist = gr::blocks::count_bits16 (diff_bits); + curr_dist = gr::blocks::count_bits16(diff_bits); if (curr_dist < min_dist) { min_dist = curr_dist; @@ -145,7 +142,7 @@ amsat_duv_decoder::process_10b (uint16_t word, size_t write_pos) while ((i < 256) && (min_dist > 0)) { diff_bits = (word ^ (d_lookup_8b10b[1][i])) & 0x3FF; - curr_dist = gr::blocks::count_bits16 (diff_bits); + curr_dist = gr::blocks::count_bits16(diff_bits); if (curr_dist < min_dist) { min_dist = curr_dist; @@ -164,25 +161,25 @@ amsat_duv_decoder::process_10b (uint16_t word, size_t write_pos) } inline uint16_t -amsat_duv_decoder::pack_10b_word (size_t idx) +amsat_duv_decoder::pack_10b_word(size_t idx) { return (((uint16_t) d_bitstream[idx] & 0x1) << 9) - | (((uint16_t) d_bitstream[idx + 1] & 0x1) << 8) - | (((uint16_t) d_bitstream[idx + 2] & 0x1) << 7) - | (((uint16_t) d_bitstream[idx + 3] & 0x1) << 6) - | (((uint16_t) d_bitstream[idx + 4] & 0x1) << 5) - | (((uint16_t) d_bitstream[idx + 5] & 0x1) << 4) - | (((uint16_t) d_bitstream[idx + 6] & 0x1) << 3) - | (((uint16_t) d_bitstream[idx + 7] & 0x1) << 2) - | (((uint16_t) d_bitstream[idx + 8] & 0x1) << 1) - | (d_bitstream[idx + 9] & 0x1); + | (((uint16_t) d_bitstream[idx + 1] & 0x1) << 8) + | (((uint16_t) d_bitstream[idx + 2] & 0x1) << 7) + | (((uint16_t) d_bitstream[idx + 3] & 0x1) << 6) + | (((uint16_t) d_bitstream[idx + 4] & 0x1) << 5) + | (((uint16_t) d_bitstream[idx + 5] & 0x1) << 4) + | (((uint16_t) d_bitstream[idx + 6] & 0x1) << 3) + | (((uint16_t) d_bitstream[idx + 7] & 0x1) << 2) + | (((uint16_t) d_bitstream[idx + 8] & 0x1) << 1) + | (d_bitstream[idx + 9] & 0x1); } static inline bool -is_spacecraft_valid (uint8_t id) +is_spacecraft_valid(uint8_t id) { for (size_t i = 0; i < sizeof(amsat_duv_decoder::amsat_fox_spacecraft_id); - i++) { + i++) { if (amsat_duv_decoder::amsat_fox_spacecraft_id[i] == id) { return true; } @@ -191,9 +188,9 @@ is_spacecraft_valid (uint8_t id) } decoder_status_t -amsat_duv_decoder::decode (const void *in, int len) +amsat_duv_decoder::decode(const void *in, int len) { - const uint8_t *input = (const uint8_t*) in; + const uint8_t *input = (const uint8_t *) in; decoder_status_t status; int ret; uint16_t word; @@ -201,110 +198,109 @@ amsat_duv_decoder::decode (const void *in, int len) /* Due to internal buffering we consume all the availabele symbols */ for (int i = 0; i < len; i++) { - d_bitstream.push_back (input[i]); + d_bitstream.push_back(input[i]); } status.consumed = len; while (1) { bool cont = false; - if(d_bitstream.size() < 11) { + if (d_bitstream.size() < 11) { return status; } - switch (d_state) - { - case SEARCH_SYNC: - for (size_t i = 0; i < d_bitstream.size (); i++) { - d_data_reg = (d_data_reg << 1) | (d_bitstream[i] & 0x1); - d_wrong_bits = (d_data_reg ^ d_control_symbol_pos) & 0x3FF; - d_wrong_bits_neg = (d_data_reg ^ d_control_symbol_neg) & 0x3FF; - d_nwrong = gr::blocks::count_bits16 (d_wrong_bits); - d_nwrong_neg = gr::blocks::count_bits16 (d_wrong_bits_neg); + switch (d_state) { + case SEARCH_SYNC: + for (size_t i = 0; i < d_bitstream.size(); i++) { + d_data_reg = (d_data_reg << 1) | (d_bitstream[i] & 0x1); + d_wrong_bits = (d_data_reg ^ d_control_symbol_pos) & 0x3FF; + d_wrong_bits_neg = (d_data_reg ^ d_control_symbol_neg) & 0x3FF; + d_nwrong = gr::blocks::count_bits16(d_wrong_bits); + d_nwrong_neg = gr::blocks::count_bits16(d_wrong_bits_neg); - /* we found the controls symbol */ - if ((d_nwrong == 0) || (d_nwrong_neg == 0)) { - d_erasure_cnt = 0; - d_word_cnt = 0; - d_state = DECODING; - if(i > 10) { - d_bitstream_idx = 9; - d_bitstream.erase (d_bitstream.begin (), - d_bitstream.begin () + i + 1 - 9); - } - else { - d_bitstream_idx = i; - d_bitstream.pop_front(); - } - return status; + /* we found the controls symbol */ + if ((d_nwrong == 0) || (d_nwrong_neg == 0)) { + d_erasure_cnt = 0; + d_word_cnt = 0; + d_state = DECODING; + if (i > 10) { + d_bitstream_idx = 9; + d_bitstream.erase(d_bitstream.begin(), + d_bitstream.begin() + i + 1 - 9); + } + else { + d_bitstream_idx = i; + d_bitstream.pop_front(); } - } - /* No SYNC found on the entire buffer. Clear it and return */ - d_bitstream.clear (); - return status; - case DECODING: - available = d_bitstream.size() - d_bitstream_idx; - if(available < 10) { return status; } - /* - * From now one, we have a SYNC so we process the data - * in chunks of 10 bits - */ - for (size_t i = 0; i < available / 10; i++, d_bitstream_idx += 10) { - word = pack_10b_word (d_bitstream_idx); - - /* Revert 10b to 8b and accumulate! */ - process_10b (word, d_word_cnt); - d_word_cnt++; - - if (d_word_cnt == max_frame_len ()) { - d_state = SEARCH_SYNC; - d_data_reg = 0; - - if (d_erasure_cnt > 0) { - ret = decode_rs_8 (d_8b_words, d_erasures_indexes, d_erasure_cnt, - 255 - max_frame_len ()); - } - else { - ret = decode_rs_8 (d_8b_words, NULL, 0, 255 - max_frame_len ()); - } - if (ret > -1) { - uint8_t fox_id = d_8b_words[0] & 0x7; - if (is_spacecraft_valid (fox_id)) { - metadata::add_pdu (status.data, d_8b_words, - amsat_fox_duv_frame_size); - metadata::add_symbol_erasures (status.data, d_erasure_cnt); - metadata::add_corrected_bits (status.data, ret); - metadata::add_time_iso8601 (status.data); - status.decode_success = true; - d_bitstream.erase (d_bitstream.begin (), - d_bitstream.begin () + (i + 1) * 10 + 1); - return status; - } - } - /* Frame could not be decoded. Retry to sync */ - cont = true; - break; - } - } - - if(cont) { - continue; - } - return status; - default: - throw std::invalid_argument ( - "amsat_duv_decoder: Invalid decoding state"); } + /* No SYNC found on the entire buffer. Clear it and return */ + d_bitstream.clear(); + return status; + case DECODING: + available = d_bitstream.size() - d_bitstream_idx; + if (available < 10) { + return status; + } + /* + * From now one, we have a SYNC so we process the data + * in chunks of 10 bits + */ + for (size_t i = 0; i < available / 10; i++, d_bitstream_idx += 10) { + word = pack_10b_word(d_bitstream_idx); + + /* Revert 10b to 8b and accumulate! */ + process_10b(word, d_word_cnt); + d_word_cnt++; + + if (d_word_cnt == max_frame_len()) { + d_state = SEARCH_SYNC; + d_data_reg = 0; + + if (d_erasure_cnt > 0) { + ret = decode_rs_8(d_8b_words, d_erasures_indexes, d_erasure_cnt, + 255 - max_frame_len()); + } + else { + ret = decode_rs_8(d_8b_words, NULL, 0, 255 - max_frame_len()); + } + if (ret > -1) { + uint8_t fox_id = d_8b_words[0] & 0x7; + if (is_spacecraft_valid(fox_id)) { + metadata::add_pdu(status.data, d_8b_words, + amsat_fox_duv_frame_size); + metadata::add_symbol_erasures(status.data, d_erasure_cnt); + metadata::add_corrected_bits(status.data, ret); + metadata::add_time_iso8601(status.data); + status.decode_success = true; + d_bitstream.erase(d_bitstream.begin(), + d_bitstream.begin() + (i + 1) * 10 + 1); + return status; + } + } + /* Frame could not be decoded. Retry to sync */ + cont = true; + break; + } + } + + if (cont) { + continue; + } + return status; + default: + throw std::invalid_argument( + "amsat_duv_decoder: Invalid decoding state"); + } } } void -amsat_duv_decoder::reset () +amsat_duv_decoder::reset() { d_erasure_cnt = 0; d_word_cnt = 0; d_state = SEARCH_SYNC; - d_bitstream.clear (); + d_bitstream.clear(); d_bitstream_idx = 0; } diff --git a/lib/ax25_decoder.cc b/lib/ax25_decoder.cc index 08a9e8a..765ba94 100644 --- a/lib/ax25_decoder.cc +++ b/lib/ax25_decoder.cc @@ -27,44 +27,42 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { decoder::decoder_sptr -ax25_decoder::make (const std::string &addr, uint8_t ssid, bool promisc, - bool descramble, bool crc_check, size_t max_frame_len) +ax25_decoder::make(const std::string &addr, uint8_t ssid, bool promisc, + bool descramble, bool crc_check, size_t max_frame_len) { - return decoder::decoder_sptr ( - new ax25_decoder (addr, ssid, promisc, descramble, crc_check, - max_frame_len)); + return decoder::decoder_sptr( + new ax25_decoder(addr, ssid, promisc, descramble, crc_check, + max_frame_len)); } -ax25_decoder::ax25_decoder (const std::string &addr, uint8_t ssid, bool promisc, - bool descramble, bool crc_check, size_t max_frame_len) : - decoder (sizeof(uint8_t), 2 * max_frame_len * 8), - d_promisc (promisc), - d_descramble (descramble), - d_crc_check(crc_check), - d_max_frame_len (max_frame_len), - d_state (NO_SYNC), - d_shift_reg (0x0), - d_dec_b (0x0), - d_prev_bit_nrzi (0), - d_received_bytes (0), - d_decoded_bits (0), - d_lfsr (0x21, 0x0, 16), - d_frame_buffer ( - new uint8_t[max_frame_len + AX25_MAX_ADDR_LEN + AX25_MAX_CTRL_LEN - + sizeof(uint16_t)]), - d_start_idx (0), - d_frame_start(0) +ax25_decoder::ax25_decoder(const std::string &addr, uint8_t ssid, bool promisc, + bool descramble, bool crc_check, size_t max_frame_len) : + decoder(sizeof(uint8_t), 2 * max_frame_len * 8), + d_promisc(promisc), + d_descramble(descramble), + d_crc_check(crc_check), + d_max_frame_len(max_frame_len), + d_state(NO_SYNC), + d_shift_reg(0x0), + d_dec_b(0x0), + d_prev_bit_nrzi(0), + d_received_bytes(0), + d_decoded_bits(0), + d_lfsr(0x21, 0x0, 16), + d_frame_buffer( + new uint8_t[max_frame_len + AX25_MAX_ADDR_LEN + AX25_MAX_CTRL_LEN + + sizeof(uint16_t)]), + d_start_idx(0), + d_frame_start(0) { } decoder_status_t -ax25_decoder::decode (const void *in, int len) +ax25_decoder::decode(const void *in, int len) { const uint8_t *input = (const uint8_t *) in; decoder_status_t status; @@ -73,8 +71,8 @@ ax25_decoder::decode (const void *in, int len) /* Perform NRZI decoding */ uint8_t b = (~((input[i] - d_prev_bit_nrzi) % 2)) & 0x1; d_prev_bit_nrzi = input[i]; - b = d_lfsr.next_bit_descramble (b); - d_bitstream.push_back (b); + b = d_lfsr.next_bit_descramble(b); + d_bitstream.push_back(b); } } else { @@ -82,7 +80,7 @@ ax25_decoder::decode (const void *in, int len) /* Perform NRZI decoding */ uint8_t b = (~((input[i] - d_prev_bit_nrzi) % 2)) & 0x1; d_prev_bit_nrzi = input[i]; - d_bitstream.push_back (b); + d_bitstream.push_back(b); } } /* @@ -95,122 +93,121 @@ ax25_decoder::decode (const void *in, int len) } void -ax25_decoder::reset () +ax25_decoder::reset() { reset_state(); } bool -ax25_decoder::_decode (decoder_status_t& status) +ax25_decoder::_decode(decoder_status_t &status) { while (1) { bool cont = false; - switch (d_state) - { - case NO_SYNC: - for (size_t i = 0; i < d_bitstream.size (); i++) { - decode_1b (d_bitstream[i]); - if (d_shift_reg == AX25_SYNC_FLAG) { - d_bitstream.erase (d_bitstream.begin (), - d_bitstream.begin () + i + 1); - enter_sync_state (); - d_frame_start = i; - d_start_idx = 0; + switch (d_state) { + case NO_SYNC: + for (size_t i = 0; i < d_bitstream.size(); i++) { + decode_1b(d_bitstream[i]); + if (d_shift_reg == AX25_SYNC_FLAG) { + d_bitstream.erase(d_bitstream.begin(), + d_bitstream.begin() + i + 1); + enter_sync_state(); + d_frame_start = i; + d_start_idx = 0; + cont = true; + break; + } + } + if (cont) { + continue; + } + d_bitstream.clear(); + return false; + case IN_SYNC: + /* + * Most of the transmitters repeat several times the AX.25 SYNC + * In case of G3RUH this is mandatory to allow the self synchronizing + * scrambler to settle + */ + for (size_t i = d_start_idx; i < d_bitstream.size(); i++) { + decode_1b(d_bitstream[i]); + d_decoded_bits++; + if (d_decoded_bits == 8) { + /* Perhaps we are in frame! */ + if (d_shift_reg != AX25_SYNC_FLAG) { + d_start_idx = i + 1; + enter_decoding_state(); cont = true; break; } + d_decoded_bits = 0; } - if(cont) { - continue; + } + if (cont) { + continue; + } + d_start_idx = d_bitstream.size(); + return false; + case DECODING: + for (size_t i = d_start_idx; i < d_bitstream.size(); i++) { + decode_1b(d_bitstream[i]); + if (d_shift_reg == AX25_SYNC_FLAG) { + LOG_DEBUG("Found frame end"); + if (enter_frame_end(status)) { + d_bitstream.erase(d_bitstream.begin(), + d_bitstream.begin() + i + 1); + d_start_idx = d_bitstream.size(); + return true; + } + cont = true; + break; } - d_bitstream.clear (); - return false; - case IN_SYNC: - /* - * Most of the transmitters repeat several times the AX.25 SYNC - * In case of G3RUH this is mandatory to allow the self synchronizing - * scrambler to settle - */ - for (size_t i = d_start_idx; i < d_bitstream.size (); i++) { - decode_1b (d_bitstream[i]); + else if ((d_shift_reg & 0xfc) == 0x7c) { + /*This was a stuffed bit */ + d_dec_b <<= 1; + } + else if ((d_shift_reg & 0xfe) == 0xfe) { + LOG_DEBUG("Invalid shift register value %u", d_received_bytes); + reset_state(); + cont = true; + break; + } + else { d_decoded_bits++; if (d_decoded_bits == 8) { - /* Perhaps we are in frame! */ - if (d_shift_reg != AX25_SYNC_FLAG) { - d_start_idx = i + 1; - enter_decoding_state (); + d_frame_buffer[d_received_bytes++] = d_dec_b; + d_decoded_bits = 0; + + /*Check if the frame limit was reached */ + if (d_received_bytes >= d_max_frame_len) { + LOG_DEBUG("Wrong size"); + reset_state(); cont = true; break; } - d_decoded_bits = 0; } } - if(cont) { - continue; - } - d_start_idx = d_bitstream.size (); - return false; - case DECODING: - for (size_t i = d_start_idx; i < d_bitstream.size (); i++) { - decode_1b (d_bitstream[i]); - if (d_shift_reg == AX25_SYNC_FLAG) { - LOG_DEBUG("Found frame end"); - if (enter_frame_end (status)) { - d_bitstream.erase (d_bitstream.begin (), - d_bitstream.begin () + i + 1); - d_start_idx = d_bitstream.size (); - return true; - } - cont = true; - break; - } - else if ((d_shift_reg & 0xfc) == 0x7c) { - /*This was a stuffed bit */ - d_dec_b <<= 1; - } - else if ((d_shift_reg & 0xfe) == 0xfe) { - LOG_DEBUG("Invalid shift register value %u", d_received_bytes); - reset_state (); - cont = true; - break; - } - else { - d_decoded_bits++; - if (d_decoded_bits == 8) { - d_frame_buffer[d_received_bytes++] = d_dec_b; - d_decoded_bits = 0; - - /*Check if the frame limit was reached */ - if (d_received_bytes >= d_max_frame_len) { - LOG_DEBUG("Wrong size"); - reset_state (); - cont = true; - break; - } - } - } - } - if(cont) { - continue; - } - d_start_idx = d_bitstream.size (); - return false; - default: - LOG_ERROR("Invalid decoding state"); - reset_state (); - return false; } + if (cont) { + continue; + } + d_start_idx = d_bitstream.size(); + return false; + default: + LOG_ERROR("Invalid decoding state"); + reset_state(); + return false; + } } } -ax25_decoder::~ax25_decoder () +ax25_decoder::~ax25_decoder() { delete[] d_frame_buffer; } void -ax25_decoder::reset_state () +ax25_decoder::reset_state() { d_state = NO_SYNC; d_dec_b = 0x0; @@ -220,7 +217,7 @@ ax25_decoder::reset_state () } void -ax25_decoder::enter_sync_state () +ax25_decoder::enter_sync_state() { d_state = IN_SYNC; d_dec_b = 0x0; @@ -230,7 +227,7 @@ ax25_decoder::enter_sync_state () } void -ax25_decoder::enter_decoding_state () +ax25_decoder::enter_decoding_state() { uint8_t tmp; d_state = DECODING; @@ -254,14 +251,14 @@ ax25_decoder::enter_decoding_state () } bool -ax25_decoder::enter_frame_end (decoder_status_t& status) +ax25_decoder::enter_frame_end(decoder_status_t &status) { uint16_t fcs; uint16_t recv_fcs = 0x0; /* First check if the size of the frame is valid */ if (d_received_bytes < AX25_MIN_ADDR_LEN + sizeof(uint16_t)) { - reset_state (); + reset_state(); return false; } @@ -269,22 +266,22 @@ ax25_decoder::enter_frame_end (decoder_status_t& status) * Check if the frame is correct using the FCS field * Using this field also try to correct up to 2 error bits */ - if (frame_check ()) { + if (frame_check()) { metadata::add_pdu(status.data, d_frame_buffer, d_received_bytes - sizeof(uint16_t)); metadata::add_time_iso8601(status.data); metadata::add_crc_valid(status.data, true); metadata::add_sample_start(status.data, d_frame_start); status.decode_success = true; - reset_state (); + reset_state(); return true; } - else if(!d_crc_check){ + else if (!d_crc_check) { metadata::add_pdu(status.data, d_frame_buffer, d_received_bytes - sizeof(uint16_t)); metadata::add_time_iso8601(status.data); metadata::add_crc_valid(status.data, false); status.decode_success = true; LOG_DEBUG("Wrong crc"); - reset_state (); + reset_state(); return false; } return false; @@ -292,7 +289,7 @@ ax25_decoder::enter_frame_end (decoder_status_t& status) inline void -ax25_decoder::decode_1b (uint8_t in) +ax25_decoder::decode_1b(uint8_t in) { /* In AX.25 the LS bit is sent first */ @@ -301,16 +298,16 @@ ax25_decoder::decode_1b (uint8_t in) } bool -ax25_decoder::frame_check () +ax25_decoder::frame_check() { uint16_t fcs; uint16_t recv_fcs = 0x0; uint8_t orig_byte; /* Check if the frame is correct using the FCS field */ - fcs = ax25_fcs (d_frame_buffer, d_received_bytes - sizeof(uint16_t)); + fcs = ax25_fcs(d_frame_buffer, d_received_bytes - sizeof(uint16_t)); recv_fcs = (((uint16_t) d_frame_buffer[d_received_bytes - 1]) << 8) - | d_frame_buffer[d_received_bytes - 2]; + | d_frame_buffer[d_received_bytes - 2]; if (fcs == recv_fcs) { return true; } diff --git a/lib/ax25_encoder_mb_impl.cc b/lib/ax25_encoder_mb_impl.cc index 6ca8766..0be20bf 100644 --- a/lib/ax25_encoder_mb_impl.cc +++ b/lib/ax25_encoder_mb_impl.cc @@ -28,160 +28,158 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +ax25_encoder_mb::sptr +ax25_encoder_mb::make(const std::string &dest_addr, uint8_t dest_ssid, + const std::string &src_addr, uint8_t src_ssid, + size_t preamble_len, size_t postamble_len, + bool scramble) { - namespace satnogs - { - - ax25_encoder_mb::sptr - ax25_encoder_mb::make (const std::string& dest_addr, uint8_t dest_ssid, - const std::string& src_addr, uint8_t src_ssid, - size_t preamble_len, size_t postamble_len, - bool scramble) - { - return gnuradio::get_initial_sptr ( - new ax25_encoder_mb_impl (dest_addr, dest_ssid, src_addr, src_ssid, + return gnuradio::get_initial_sptr( + new ax25_encoder_mb_impl(dest_addr, dest_ssid, src_addr, src_ssid, preamble_len, postamble_len, scramble)); +} + +/* + * The private constructor + */ +ax25_encoder_mb_impl::ax25_encoder_mb_impl(const std::string &dest_addr, + uint8_t dest_ssid, + const std::string &src_addr, + uint8_t src_ssid, + size_t preamble_len, + size_t postabmle_len, + bool scramble) : + gr::sync_block("ax25_encoder_mb", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, 1, sizeof(uint8_t))), + d_preamble_len(preamble_len), + d_postamble_len(postabmle_len), + d_scramble(scramble), + d_remaining(0), + d_produced(0), + d_prev_bit(0x0), + d_encoded_frame( + new uint8_t[(preamble_len + postabmle_len + + (AX25_MAX_FRAME_LEN * 2)) * 8]), + d_tmp_buf( + new uint8_t[preamble_len + postabmle_len + + (AX25_MAX_FRAME_LEN * 2)]), + d_addr_field(new uint8_t[AX25_MAX_ADDR_LEN]), + d_lfsr(0x21, 0x0, 16) +{ + /* Input is a blob message containing the info field data */ + message_port_register_in(pmt::mp("info")); + d_addr_len = ax25_create_addr_field(d_addr_field, dest_addr, dest_ssid, + src_addr, src_ssid); +} + +/* + * Our virtual destructor. + */ +ax25_encoder_mb_impl::~ax25_encoder_mb_impl() +{ + delete [] d_encoded_frame; + delete [] d_tmp_buf; + delete [] d_addr_field; +} + +int +ax25_encoder_mb_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const uint8_t *info; + size_t info_len; + size_t max_avail; + size_t len; + size_t i; + pmt::pmt_t msg; + ax25_encode_status_t status; + + uint8_t *out = (uint8_t *) output_items[0]; + + /* If all the frame samples have already be sent, wait for a new frame */ + if (d_remaining == 0) { + d_produced = 0; + d_prev_bit = 0x0; + d_lfsr.reset(); + + /* Block waiting from a new message from users */ + msg = delete_head_blocking(pmt::mp("info")); + info = (const uint8_t *) pmt::blob_data(msg); + info_len = pmt::blob_length(msg); + + /* Prepare and encode the AX.25 frame */ + len = ax25_prepare_frame(d_tmp_buf, info, info_len, AX25_I_FRAME, + d_addr_field, d_addr_len, 0, 1, + d_preamble_len, d_postamble_len); + + /* Perform bit stuffing */ + status = ax25_bit_stuffing(d_encoded_frame, &d_remaining, d_tmp_buf, + len, d_preamble_len, d_postamble_len); + if (status != AX25_ENC_OK) { + LOG_ERROR("AX.25 encoding failed"); + d_remaining = 0; + return 0; } - /* - * The private constructor - */ - ax25_encoder_mb_impl::ax25_encoder_mb_impl (const std::string& dest_addr, - uint8_t dest_ssid, - const std::string& src_addr, - uint8_t src_ssid, - size_t preamble_len, - size_t postabmle_len, - bool scramble) : - gr::sync_block ("ax25_encoder_mb", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (1, 1, sizeof(uint8_t))), - d_preamble_len (preamble_len), - d_postamble_len (postabmle_len), - d_scramble (scramble), - d_remaining (0), - d_produced (0), - d_prev_bit (0x0), - d_encoded_frame ( - new uint8_t[(preamble_len + postabmle_len - + (AX25_MAX_FRAME_LEN * 2)) * 8]), - d_tmp_buf ( - new uint8_t[preamble_len + postabmle_len - + (AX25_MAX_FRAME_LEN * 2)]), - d_addr_field (new uint8_t[AX25_MAX_ADDR_LEN]), - d_lfsr (0x21, 0x0, 16) - { - /* Input is a blob message containing the info field data */ - message_port_register_in (pmt::mp ("info")); - d_addr_len = ax25_create_addr_field (d_addr_field, dest_addr, dest_ssid, - src_addr, src_ssid); - } - - /* - * Our virtual destructor. - */ - ax25_encoder_mb_impl::~ax25_encoder_mb_impl () - { - delete [] d_encoded_frame; - delete [] d_tmp_buf; - delete [] d_addr_field; - } - - int - ax25_encoder_mb_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const uint8_t *info; - size_t info_len; - size_t max_avail; - size_t len; - size_t i; - pmt::pmt_t msg; - ax25_encode_status_t status; - - uint8_t *out = (uint8_t *) output_items[0]; - - /* If all the frame samples have already be sent, wait for a new frame */ - if (d_remaining == 0) { - d_produced = 0; - d_prev_bit = 0x0; - d_lfsr.reset (); - - /* Block waiting from a new message from users */ - msg = delete_head_blocking (pmt::mp ("info")); - info = (const uint8_t *) pmt::blob_data (msg); - info_len = pmt::blob_length (msg); - - /* Prepare and encode the AX.25 frame */ - len = ax25_prepare_frame (d_tmp_buf, info, info_len, AX25_I_FRAME, - d_addr_field, d_addr_len, 0, 1, - d_preamble_len, d_postamble_len); - - /* Perform bit stuffing */ - status = ax25_bit_stuffing (d_encoded_frame, &d_remaining, d_tmp_buf, - len, d_preamble_len, d_postamble_len); - if (status != AX25_ENC_OK) { - LOG_ERROR("AX.25 encoding failed"); - d_remaining = 0; - return 0; - } - - /*Perform scrambling if the user asked for it */ - if (d_scramble) { - for (i = 0; i < d_remaining; i++) { - d_encoded_frame[i] = d_lfsr.next_bit_scramble (d_encoded_frame[i]); - } - /* Allow the LFSR to pop all its bits */ - d_remaining += 16; - for (; i < d_remaining; i++) { - d_encoded_frame[i] = d_lfsr.next_bit_scramble (0x0); - } - } - /* Append a zero byte at the end */ - memset(&d_encoded_frame[d_remaining], 0, 8); - d_remaining += 8; + /*Perform scrambling if the user asked for it */ + if (d_scramble) { + for (i = 0; i < d_remaining; i++) { + d_encoded_frame[i] = d_lfsr.next_bit_scramble(d_encoded_frame[i]); } - - /* If this is the first part of the frame add the start of burst tag*/ - if (d_produced == 0) { - add_sob (nitems_written (0)); + /* Allow the LFSR to pop all its bits */ + d_remaining += 16; + for (; i < d_remaining; i++) { + d_encoded_frame[i] = d_lfsr.next_bit_scramble(0x0); } - max_avail = std::min (d_remaining, (size_t) noutput_items); - - /* Perform NRZI encoding */ - for (i = 0; i < max_avail; i++) { - out[i] = ((0x1 & ~d_encoded_frame[i + d_produced]) + d_prev_bit) % 2; - d_prev_bit = out[i]; - } - - d_remaining -= max_avail; - d_produced += max_avail; - if (d_remaining == 0) { - add_eob (nitems_written (0) + max_avail); - } - return (int) max_avail; } + /* Append a zero byte at the end */ + memset(&d_encoded_frame[d_remaining], 0, 8); + d_remaining += 8; + } + + /* If this is the first part of the frame add the start of burst tag*/ + if (d_produced == 0) { + add_sob(nitems_written(0)); + } + max_avail = std::min(d_remaining, (size_t) noutput_items); + + /* Perform NRZI encoding */ + for (i = 0; i < max_avail; i++) { + out[i] = ((0x1 & ~d_encoded_frame[i + d_produced]) + d_prev_bit) % 2; + d_prev_bit = out[i]; + } + + d_remaining -= max_avail; + d_produced += max_avail; + if (d_remaining == 0) { + add_eob(nitems_written(0) + max_avail); + } + return (int) max_avail; +} - void - ax25_encoder_mb_impl::add_sob (uint64_t item) - { - static const pmt::pmt_t sob_key = pmt::string_to_symbol ("tx_sob"); - static const pmt::pmt_t value = pmt::PMT_T; - static const pmt::pmt_t srcid = pmt::string_to_symbol (alias ()); - add_item_tag (0, item, sob_key, value, srcid); - } +void +ax25_encoder_mb_impl::add_sob(uint64_t item) +{ + static const pmt::pmt_t sob_key = pmt::string_to_symbol("tx_sob"); + static const pmt::pmt_t value = pmt::PMT_T; + static const pmt::pmt_t srcid = pmt::string_to_symbol(alias()); + add_item_tag(0, item, sob_key, value, srcid); +} - void - ax25_encoder_mb_impl::add_eob (uint64_t item) - { - static const pmt::pmt_t eob_key = pmt::string_to_symbol ("tx_eob"); - static const pmt::pmt_t value = pmt::PMT_T; - static const pmt::pmt_t srcid = pmt::string_to_symbol (alias ()); - add_item_tag (0, item, eob_key, value, srcid); - } +void +ax25_encoder_mb_impl::add_eob(uint64_t item) +{ + static const pmt::pmt_t eob_key = pmt::string_to_symbol("tx_eob"); + static const pmt::pmt_t value = pmt::PMT_T; + static const pmt::pmt_t srcid = pmt::string_to_symbol(alias()); + add_item_tag(0, item, eob_key, value, srcid); +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/ax25_encoder_mb_impl.h b/lib/ax25_encoder_mb_impl.h index ab059ff..4f72cc1 100644 --- a/lib/ax25_encoder_mb_impl.h +++ b/lib/ax25_encoder_mb_impl.h @@ -25,45 +25,42 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class ax25_encoder_mb_impl : public ax25_encoder_mb - { - private: - const size_t d_preamble_len; - const size_t d_postamble_len; - const bool d_scramble; - size_t d_remaining; - size_t d_produced; - uint8_t d_prev_bit; - uint8_t *d_encoded_frame; - uint8_t *d_tmp_buf; - uint8_t *d_addr_field; - size_t d_addr_len; - digital::lfsr d_lfsr; +class ax25_encoder_mb_impl : public ax25_encoder_mb { +private: + const size_t d_preamble_len; + const size_t d_postamble_len; + const bool d_scramble; + size_t d_remaining; + size_t d_produced; + uint8_t d_prev_bit; + uint8_t *d_encoded_frame; + uint8_t *d_tmp_buf; + uint8_t *d_addr_field; + size_t d_addr_len; + digital::lfsr d_lfsr; - void - add_sob (uint64_t item); - void - add_eob (uint64_t item); + void + add_sob(uint64_t item); + void + add_eob(uint64_t item); - public: - ax25_encoder_mb_impl (const std::string& dest_addr, uint8_t dest_ssid, - const std::string& src_addr, uint8_t src_ssid, - size_t preamble_len, size_t postamble_len, - bool scramble); - ~ax25_encoder_mb_impl (); +public: + ax25_encoder_mb_impl(const std::string &dest_addr, uint8_t dest_ssid, + const std::string &src_addr, uint8_t src_ssid, + size_t preamble_len, size_t postamble_len, + bool scramble); + ~ax25_encoder_mb_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_AX25_ENCODER_MB_IMPL_H */ diff --git a/lib/coarse_doppler_correction_cc_impl.cc b/lib/coarse_doppler_correction_cc_impl.cc index 345df41..7e6a19d 100644 --- a/lib/coarse_doppler_correction_cc_impl.cc +++ b/lib/coarse_doppler_correction_cc_impl.cc @@ -27,103 +27,101 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +coarse_doppler_correction_cc::sptr +coarse_doppler_correction_cc::make(double target_freq, + double sampling_rate) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new coarse_doppler_correction_cc_impl(target_freq, sampling_rate)); +} - coarse_doppler_correction_cc::sptr - coarse_doppler_correction_cc::make (double target_freq, - double sampling_rate) - { - return gnuradio::get_initial_sptr ( - new coarse_doppler_correction_cc_impl (target_freq, sampling_rate)); - } +/* + * The private constructor + */ +coarse_doppler_correction_cc_impl::coarse_doppler_correction_cc_impl( + double target_freq, double sampling_rate) : + gr::sync_block("coarse_doppler_correction_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_target_freq(target_freq), + d_samp_rate(sampling_rate), + d_buf_items(std::min((size_t)8192UL, (size_t)(d_samp_rate / 4))), + d_freq_diff(0), + d_nco() +{ + message_port_register_in(pmt::mp("freq")); - /* - * The private constructor - */ - coarse_doppler_correction_cc_impl::coarse_doppler_correction_cc_impl ( - double target_freq, double sampling_rate) : - gr::sync_block ("coarse_doppler_correction_cc", - gr::io_signature::make (1, 1, sizeof(gr_complex)), - gr::io_signature::make (1, 1, sizeof(gr_complex))), - d_target_freq (target_freq), - d_samp_rate (sampling_rate), - d_buf_items (std::min ((size_t)8192UL, (size_t) (d_samp_rate / 4))), - d_freq_diff (0), - d_nco () - { - message_port_register_in (pmt::mp ("freq")); + /* + * NOTE: + * Set the maximum number of samples to be equivalent of half a second. + * With this way we are sure that at least one frequency message + * per second will be processed. + * + * This is taken into consideration due to the fact that the work() + * and the input message handler are NOT reentrant. + */ + set_max_noutput_items(d_samp_rate / 4.0); + set_alignment(8); - /* - * NOTE: - * Set the maximum number of samples to be equivalent of half a second. - * With this way we are sure that at least one frequency message - * per second will be processed. - * - * This is taken into consideration due to the fact that the work() - * and the input message handler are NOT reentrant. - */ - set_max_noutput_items (d_samp_rate / 4.0); - set_alignment (8); + set_msg_handler( + pmt::mp("freq"), + boost::bind(&coarse_doppler_correction_cc_impl::new_freq, this, _1)); - set_msg_handler ( - pmt::mp ("freq"), - boost::bind (&coarse_doppler_correction_cc_impl::new_freq, this, _1)); + d_nco.set_freq(0); + /* Allocate aligned memory for the NCO */ + d_nco_buff = (gr_complex *) volk_malloc( + (d_samp_rate / 4) * sizeof(gr_complex), 32); + if (!d_nco_buff) { + throw std::runtime_error("Could not allocate NCO memory"); + } +} - d_nco.set_freq (0); - /* Allocate aligned memory for the NCO */ - d_nco_buff = (gr_complex *) volk_malloc ( - (d_samp_rate / 4) * sizeof(gr_complex), 32); - if (!d_nco_buff) { - throw std::runtime_error ("Could not allocate NCO memory"); - } - } +void +coarse_doppler_correction_cc_impl::new_freq(pmt::pmt_t msg) +{ + boost::mutex::scoped_lock lock(d_mutex); + double new_freq; + new_freq = pmt::to_double(msg); + d_freq_diff = new_freq - d_target_freq; + d_nco.set_freq((2 * M_PI * (-d_freq_diff)) / d_samp_rate); +} - void - coarse_doppler_correction_cc_impl::new_freq (pmt::pmt_t msg) - { - boost::mutex::scoped_lock lock (d_mutex); - double new_freq; - new_freq = pmt::to_double (msg); - d_freq_diff = new_freq - d_target_freq; - d_nco.set_freq ((2 * M_PI * (-d_freq_diff)) / d_samp_rate); - } +/* + * Our virtual destructor. + */ +coarse_doppler_correction_cc_impl::~coarse_doppler_correction_cc_impl() +{ + volk_free(d_nco_buff); +} - /* - * Our virtual destructor. - */ - coarse_doppler_correction_cc_impl::~coarse_doppler_correction_cc_impl () - { - volk_free (d_nco_buff); - } +int +coarse_doppler_correction_cc_impl::work( + int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; - int - coarse_doppler_correction_cc_impl::work ( - int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; + /* Perform the correction */ + d_nco.sincos(d_nco_buff, noutput_items, 1.0); + volk_32fc_x2_multiply_32fc(out, in, d_nco_buff, noutput_items); - /* Perform the correction */ - d_nco.sincos (d_nco_buff, noutput_items, 1.0); - volk_32fc_x2_multiply_32fc (out, in, d_nco_buff, noutput_items); + // Tell runtime system how many output items we produced. + return noutput_items; +} - // Tell runtime system how many output items we produced. - return noutput_items; - } +void +coarse_doppler_correction_cc_impl::set_target_freq(double freq) +{ + boost::mutex::scoped_lock lock(d_mutex); + d_target_freq = freq; + d_freq_diff = 0.0; + d_nco.set_freq(0); +} - void - coarse_doppler_correction_cc_impl::set_target_freq (double freq) - { - boost::mutex::scoped_lock lock (d_mutex); - d_target_freq = freq; - d_freq_diff = 0.0; - d_nco.set_freq (0); - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/coarse_doppler_correction_cc_impl.h b/lib/coarse_doppler_correction_cc_impl.h index ebb2d6b..a3d632c 100644 --- a/lib/coarse_doppler_correction_cc_impl.h +++ b/lib/coarse_doppler_correction_cc_impl.h @@ -24,41 +24,38 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class coarse_doppler_correction_cc_impl : public coarse_doppler_correction_cc - { - private: - double d_target_freq; - const double d_samp_rate; - const size_t d_buf_items; - double d_freq_diff; +class coarse_doppler_correction_cc_impl : public coarse_doppler_correction_cc { +private: + double d_target_freq; + const double d_samp_rate; + const size_t d_buf_items; + double d_freq_diff; - gr::fxpt_nco d_nco; - gr_complex *d_nco_buff; - boost::mutex d_mutex; + gr::fxpt_nco d_nco; + gr_complex *d_nco_buff; + boost::mutex d_mutex; - void - new_freq (pmt::pmt_t msg); + void + new_freq(pmt::pmt_t msg); - public: - coarse_doppler_correction_cc_impl (double target_freq, - double sampling_rate); - ~coarse_doppler_correction_cc_impl (); +public: + coarse_doppler_correction_cc_impl(double target_freq, + double sampling_rate); + ~coarse_doppler_correction_cc_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); - void - set_target_freq (double freq); - }; + void + set_target_freq(double freq); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_COARSE_DOPPLER_CORRECTION_CC_IMPL_H */ diff --git a/lib/convolutional_deinterleaver.cc b/lib/convolutional_deinterleaver.cc index 20be14d..fe16a78 100644 --- a/lib/convolutional_deinterleaver.cc +++ b/lib/convolutional_deinterleaver.cc @@ -25,28 +25,26 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -convolutional_deinterleaver::convolutional_deinterleaver (size_t branches, - size_t M) : - d_nbranches (branches), - d_M (M), - d_idx(0) +convolutional_deinterleaver::convolutional_deinterleaver(size_t branches, + size_t M) : + d_nbranches(branches), + d_M(M), + d_idx(0) { - for(size_t i = 0; i < d_nbranches; i++) { + for (size_t i = 0; i < d_nbranches; i++) { d_branches.push_back(std::deque((d_nbranches - 1 - i) * M, 0)); } } -convolutional_deinterleaver::~convolutional_deinterleaver () +convolutional_deinterleaver::~convolutional_deinterleaver() { } uint8_t -convolutional_deinterleaver::decode_bit (uint8_t b) +convolutional_deinterleaver::decode_bit(uint8_t b) { uint8_t ret; d_branches[d_idx].push_back(b); @@ -57,7 +55,7 @@ convolutional_deinterleaver::decode_bit (uint8_t b) } uint8_t -convolutional_deinterleaver::decode_byte (uint8_t b) +convolutional_deinterleaver::decode_byte(uint8_t b) { uint8_t ret = 0; ret = decode_bit(b >> 7) << 7; @@ -72,10 +70,10 @@ convolutional_deinterleaver::decode_byte (uint8_t b) } void -convolutional_deinterleaver::reset () +convolutional_deinterleaver::reset() { d_branches.clear(); - for(size_t i = 0; i < d_nbranches; i++) { + for (size_t i = 0; i < d_nbranches; i++) { d_branches.push_back(std::deque((d_nbranches - 1 - i) * d_M, 0)); } d_idx = 0; diff --git a/lib/crc.cc b/lib/crc.cc index b5ac7d8..4de3ae2 100644 --- a/lib/crc.cc +++ b/lib/crc.cc @@ -25,73 +25,73 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -const uint16_t crc::crc16_ccitt_table_reverse[256] = - { 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48, - 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 0x1081, 0x0108, - 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 0x9CC9, 0x8D40, 0xBFDB, - 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 0x2102, 0x308B, 0x0210, 0x1399, - 0x6726, 0x76AF, 0x4434, 0x55BD, 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, - 0xFAE7, 0xC87C, 0xD9F5, 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, - 0x54B5, 0x453C, 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, - 0xC974, 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, - 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 0x5285, - 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 0xDECD, 0xCF44, - 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 0x6306, 0x728F, 0x4014, - 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, - 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, - 0x242A, 0x16B1, 0x0738, 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, - 0x9AF9, 0x8B70, 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, - 0xF0B7, 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, - 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 0x18C1, - 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 0xA50A, 0xB483, - 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 0x2942, 0x38CB, 0x0A50, - 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 0xB58B, 0xA402, 0x9699, 0x8710, - 0xF3AF, 0xE226, 0xD0BD, 0xC134, 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, - 0x6E6E, 0x5CF5, 0x4D7C, 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, - 0xA33A, 0xB2B3, 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, - 0x3EFB, 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, - 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 0xE70E, - 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 0x6B46, 0x7ACF, - 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 0xF78F, 0xE606, 0xD49D, - 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 0x7BC7, 0x6A4E, 0x58D5, 0x495C, - 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 }; +const uint16_t crc::crc16_ccitt_table_reverse[256] = { + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48, + 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 0x1081, 0x0108, + 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 0x9CC9, 0x8D40, 0xBFDB, + 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 0x2102, 0x308B, 0x0210, 0x1399, + 0x6726, 0x76AF, 0x4434, 0x55BD, 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, + 0xFAE7, 0xC87C, 0xD9F5, 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, + 0x54B5, 0x453C, 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, + 0xC974, 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 0x5285, + 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 0xDECD, 0xCF44, + 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 0x6306, 0x728F, 0x4014, + 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, + 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, + 0x242A, 0x16B1, 0x0738, 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, + 0x9AF9, 0x8B70, 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, + 0xF0B7, 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 0x18C1, + 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 0xA50A, 0xB483, + 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 0x2942, 0x38CB, 0x0A50, + 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 0xB58B, 0xA402, 0x9699, 0x8710, + 0xF3AF, 0xE226, 0xD0BD, 0xC134, 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, + 0x6E6E, 0x5CF5, 0x4D7C, 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, + 0xA33A, 0xB2B3, 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, + 0x3EFB, 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 0xE70E, + 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 0x6B46, 0x7ACF, + 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 0xF78F, 0xE606, 0xD49D, + 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 0x7BC7, 0x6A4E, 0x58D5, 0x495C, + 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 +}; -const uint16_t crc::crc16_ccitt_table[256] = - { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, - 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, - 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, - 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, - 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, - 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, - 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, - 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, - 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, - 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, - 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, - 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, - 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, - 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, - 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, - 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, - 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, - 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, - 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, - 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, - 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, - 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, - 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, - 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, - 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, - 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; +const uint16_t crc::crc16_ccitt_table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, + 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, + 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, + 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, + 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, + 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, + 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, + 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, + 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, + 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, + 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, + 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, + 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, + 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, + 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, + 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, + 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, + 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, + 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, + 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, + 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, + 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, + 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, + 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; uint16_t crc::crc16_ccitt_reversed(const uint8_t *data, size_t len) @@ -104,7 +104,7 @@ crc::crc16_ccitt_reversed(const uint8_t *data, size_t len) } uint16_t -crc::crc16_ccitt (const uint8_t *data, size_t len) +crc::crc16_ccitt(const uint8_t *data, size_t len) { uint16_t crc = 0; while (len-- != 0) { @@ -124,7 +124,7 @@ crc::crc16_ax25(const uint8_t *data, size_t len) } static uint16_t -update_crc16_ibm (uint8_t crc, uint16_t reg) +update_crc16_ibm(uint8_t crc, uint16_t reg) { const uint16_t crc_poly = 0x8005; for (size_t i = 0; i < 8; i++) { @@ -143,8 +143,9 @@ uint16_t crc::crc16_ibm(const uint8_t *data, size_t len) { uint16_t crc = 0xFFFF; - for (size_t i = 0; i < len; i++) - crc = update_crc16_ibm (data[i], crc); + for (size_t i = 0; i < len; i++) { + crc = update_crc16_ibm(data[i], crc); + } return crc; } diff --git a/lib/cw_encoder_impl.cc b/lib/cw_encoder_impl.cc index 9f6db03..0d80906 100644 --- a/lib/cw_encoder_impl.cc +++ b/lib/cw_encoder_impl.cc @@ -28,118 +28,118 @@ #include "cw_encoder_impl.h" namespace gr { - namespace satnogs { +namespace satnogs { - cw_encoder::sptr - cw_encoder::make(double samp_rate, double cw_freq, size_t wpm) - { - return gnuradio::get_initial_sptr - (new cw_encoder_impl(samp_rate, cw_freq, wpm)); +cw_encoder::sptr +cw_encoder::make(double samp_rate, double cw_freq, size_t wpm) +{ + return gnuradio::get_initial_sptr + (new cw_encoder_impl(samp_rate, cw_freq, wpm)); +} + +/* + * The private constructor + */ +cw_encoder_impl::cw_encoder_impl(double samp_rate, double cw_freq, + size_t wpm) + : gr::sync_block("cw_encoder", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_samp_rate(samp_rate), + d_cw_freq(cw_freq), + d_wpm(wpm), + d_dot_samples((1.2 / wpm) / (1.0 / samp_rate)), + d_window_size(0), + d_windows_remaining(0), + d_cw_symbol(MORSE_L_SPACE), + d_nco() +{ + message_port_register_in(pmt::mp("symbol")); + + /* + * Try to split the CW pulses in smaller windows for dealing efficiently + * with the available buffer size + */ + size_t i = 10; + d_window_size = d_dot_samples / i; + while (d_window_size > 200) { + i += 10; + d_window_size = d_dot_samples / i; + } + + /* NOTE: The dot duration should be a perfect multiple of the window */ + while (d_dot_samples % d_window_size != 0) { + d_window_size++; + } + + set_output_multiple(d_window_size); + d_nco.set_freq((2 * M_PI * cw_freq) / samp_rate); +} + +/* + * Our virtual destructor. + */ +cw_encoder_impl::~cw_encoder_impl() +{ +} + +int +cw_encoder_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t available; + size_t i; + gr_complex *out = (gr_complex *) output_items[0]; + + if (noutput_items < 0) { + return noutput_items; + } + + if (d_windows_remaining == 0) { + pmt::pmt_t symbol = delete_head_blocking(pmt::mp("symbol")); + d_cw_symbol = (morse_symbol_t) pmt::to_long(symbol); + /* Reset NCO so the amplitude starts from zero */ + d_nco.set_freq((2 * M_PI * d_cw_freq) / d_samp_rate); + switch (d_cw_symbol) { + case MORSE_DOT: + case MORSE_INTRA_SPACE: + d_windows_remaining = d_dot_samples / d_window_size; + break; + case MORSE_DASH: + case MORSE_S_SPACE: + d_windows_remaining = (d_dot_samples / d_window_size) * 3; + break; + case MORSE_L_SPACE: + d_windows_remaining = (d_dot_samples / d_window_size) * 7; + break; + default: + LOG_WARN("Unrecognized CW symbol"); + return 0; } + } - /* - * The private constructor - */ - cw_encoder_impl::cw_encoder_impl(double samp_rate, double cw_freq, - size_t wpm) - : gr::sync_block("cw_encoder", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(1, 1, sizeof(gr_complex))), - d_samp_rate (samp_rate), - d_cw_freq (cw_freq), - d_wpm (wpm), - d_dot_samples ((1.2 / wpm) / (1.0 / samp_rate)), - d_window_size (0), - d_windows_remaining (0), - d_cw_symbol (MORSE_L_SPACE), - d_nco () - { - message_port_register_in(pmt::mp("symbol")); - - /* - * Try to split the CW pulses in smaller windows for dealing efficiently - * with the available buffer size - */ - size_t i = 10; - d_window_size = d_dot_samples / i; - while(d_window_size > 200) { - i += 10; - d_window_size = d_dot_samples / i; - } - - /* NOTE: The dot duration should be a perfect multiple of the window */ - while(d_dot_samples % d_window_size != 0) { - d_window_size++; - } - - set_output_multiple(d_window_size); - d_nco.set_freq ((2 * M_PI * cw_freq) / samp_rate); + for (i = 0; i < (size_t)noutput_items / d_window_size; i++) { + switch (d_cw_symbol) { + case MORSE_S_SPACE: + case MORSE_L_SPACE: + case MORSE_INTRA_SPACE: + memset(out + i * d_window_size, 0, + d_window_size * sizeof(gr_complex)); + break; + case MORSE_DOT: + case MORSE_DASH: + d_nco.sincos(out + i * d_window_size, d_window_size, 1.0); + break; } - - /* - * Our virtual destructor. - */ - cw_encoder_impl::~cw_encoder_impl() - { + d_windows_remaining--; + if (d_windows_remaining == 0) { + return (i + 1) * d_window_size; } + } + return i * d_window_size; +} - int - cw_encoder_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - size_t available; - size_t i; - gr_complex *out = (gr_complex *) output_items[0]; - - if(noutput_items < 0) { - return noutput_items; - } - - if(d_windows_remaining == 0) { - pmt::pmt_t symbol = delete_head_blocking(pmt::mp("symbol")); - d_cw_symbol = (morse_symbol_t) pmt::to_long(symbol); - /* Reset NCO so the amplitude starts from zero */ - d_nco.set_freq ((2 * M_PI * d_cw_freq) / d_samp_rate); - switch(d_cw_symbol) { - case MORSE_DOT: - case MORSE_INTRA_SPACE: - d_windows_remaining = d_dot_samples / d_window_size; - break; - case MORSE_DASH: - case MORSE_S_SPACE: - d_windows_remaining = (d_dot_samples / d_window_size) * 3; - break; - case MORSE_L_SPACE: - d_windows_remaining = (d_dot_samples / d_window_size) * 7; - break; - default: - LOG_WARN("Unrecognized CW symbol"); - return 0; - } - } - - for(i = 0; i < (size_t)noutput_items / d_window_size; i++) { - switch(d_cw_symbol){ - case MORSE_S_SPACE: - case MORSE_L_SPACE: - case MORSE_INTRA_SPACE: - memset (out + i * d_window_size, 0, - d_window_size * sizeof(gr_complex)); - break; - case MORSE_DOT: - case MORSE_DASH: - d_nco.sincos(out + i * d_window_size, d_window_size, 1.0); - break; - } - d_windows_remaining--; - if(d_windows_remaining == 0) { - return (i + 1) * d_window_size; - } - } - return i * d_window_size; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/cw_encoder_impl.h b/lib/cw_encoder_impl.h index 747cf8d..b706f0a 100644 --- a/lib/cw_encoder_impl.h +++ b/lib/cw_encoder_impl.h @@ -28,39 +28,36 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class cw_encoder_impl : public cw_encoder - { - private: - const double d_samp_rate; - const double d_cw_freq; - const size_t d_wpm; - const size_t d_dot_samples; - size_t d_window_size; - size_t d_windows_remaining; - morse_symbol_t d_cw_symbol; - gr::fxpt_nco d_nco; +class cw_encoder_impl : public cw_encoder { +private: + const double d_samp_rate; + const double d_cw_freq; + const size_t d_wpm; + const size_t d_dot_samples; + size_t d_window_size; + size_t d_windows_remaining; + morse_symbol_t d_cw_symbol; + gr::fxpt_nco d_nco; - std::string - get_cw_symbol(char c); + std::string + get_cw_symbol(char c); - public: - cw_encoder_impl (double samp_rate, double cw_freq, size_t wpm); - ~cw_encoder_impl (); +public: + cw_encoder_impl(double samp_rate, double cw_freq, size_t wpm); + ~cw_encoder_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_CW_ENCODER_IMPL_H */ diff --git a/lib/cw_to_symbol_impl.cc b/lib/cw_to_symbol_impl.cc index 3d5648a..c8fceb1 100644 --- a/lib/cw_to_symbol_impl.cc +++ b/lib/cw_to_symbol_impl.cc @@ -37,66 +37,64 @@ #endif #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { cw_to_symbol::sptr -cw_to_symbol::make (double sampling_rate, float threshold, float conf_level, - size_t wpm, size_t hysteresis) +cw_to_symbol::make(double sampling_rate, float threshold, float conf_level, + size_t wpm, size_t hysteresis) { - return gnuradio::get_initial_sptr ( - new cw_to_symbol_impl (sampling_rate, threshold, conf_level, wpm, - hysteresis)); + return gnuradio::get_initial_sptr( + new cw_to_symbol_impl(sampling_rate, threshold, conf_level, wpm, + hysteresis)); } /* * The private constructor */ -cw_to_symbol_impl::cw_to_symbol_impl (double sampling_rate, float threshold, - float conf_level, size_t wpm, - size_t hysteresis) : - gr::sync_block ("cw_to_symbol", - gr::io_signature::make (1, 1, sizeof(float)), - gr::io_signature::make (0, 0, 0)), - d_sampling_rate (sampling_rate), - d_act_thrshld (threshold), - d_confidence_level (conf_level), - d_dot_samples ((1.2 / wpm) * sampling_rate), - d_window_size (0), - d_window_cnt (0), - d_idle_cnt (0), - d_dot_windows_num (0), - d_dec_state (NO_SYNC), - d_prev_space_symbol (true) +cw_to_symbol_impl::cw_to_symbol_impl(double sampling_rate, float threshold, + float conf_level, size_t wpm, + size_t hysteresis) : + gr::sync_block("cw_to_symbol", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(0, 0, 0)), + d_sampling_rate(sampling_rate), + d_act_thrshld(threshold), + d_confidence_level(conf_level), + d_dot_samples((1.2 / wpm) * sampling_rate), + d_window_size(0), + d_window_cnt(0), + d_idle_cnt(0), + d_dot_windows_num(0), + d_dec_state(NO_SYNC), + d_prev_space_symbol(true) { if (wpm < MIN_WPM) { - throw std::invalid_argument ("Decoder can not handle such low WPM setting"); + throw std::invalid_argument("Decoder can not handle such low WPM setting"); } if (wpm > MAX_WPM) { - throw std::invalid_argument ( - "Decoder can not handle such high WPM setting"); + throw std::invalid_argument( + "Decoder can not handle such high WPM setting"); } if (conf_level > 1.0 || conf_level < 0.5) { - throw std::invalid_argument ( - "Confidence level should be in the range [0.5, 1.0]"); + throw std::invalid_argument( + "Confidence level should be in the range [0.5, 1.0]"); } - if(hysteresis > d_dot_samples / 4) { - throw std::invalid_argument ("Too large hysteresis value"); + if (hysteresis > d_dot_samples / 4) { + throw std::invalid_argument("Too large hysteresis value"); } - message_port_register_in (pmt::mp ("act_threshold")); - message_port_register_out (pmt::mp ("out")); + message_port_register_in(pmt::mp("act_threshold")); + message_port_register_out(pmt::mp("out")); /* Register the message handlers */ - set_msg_handler ( - pmt::mp ("act_threshold"), - boost::bind (&cw_to_symbol_impl::set_act_threshold_msg_handler, this, - _1)); + set_msg_handler( + pmt::mp("act_threshold"), + boost::bind(&cw_to_symbol_impl::set_act_threshold_msg_handler, this, + _1)); /* * Reconsider the dot oulse duration based on the confidence level @@ -131,29 +129,29 @@ cw_to_symbol_impl::cw_to_symbol_impl (double sampling_rate, float threshold, d_short_pause_windows_num = d_dash_windows_num; d_long_pause_windows_num = 7 * d_dot_windows_num; - const int alignment_multiple = volk_get_alignment () - / (d_window_size * sizeof(float)); - set_alignment (std::max (1, alignment_multiple)); + const int alignment_multiple = volk_get_alignment() + / (d_window_size * sizeof(float)); + set_alignment(std::max(1, alignment_multiple)); - d_const_val = (float *) volk_malloc (d_window_size * sizeof(float), - volk_get_alignment ()); - d_tmp = (float *) volk_malloc (d_window_size * sizeof(float), - volk_get_alignment ()); - d_out = (int32_t *) volk_malloc (d_window_size * sizeof(int32_t), - volk_get_alignment ()); + d_const_val = (float *) volk_malloc(d_window_size * sizeof(float), + volk_get_alignment()); + d_tmp = (float *) volk_malloc(d_window_size * sizeof(float), + volk_get_alignment()); + d_out = (int32_t *) volk_malloc(d_window_size * sizeof(int32_t), + volk_get_alignment()); if (!d_const_val || !d_tmp || !d_out) { - throw std::runtime_error ("cw_to_symbol: Could not allocate memory"); + throw std::runtime_error("cw_to_symbol: Could not allocate memory"); } for (i = 0; i < d_window_size; i++) { d_const_val[i] = threshold; } - set_history (d_window_size); + set_history(d_window_size); } inline void -cw_to_symbol_impl::send_symbol_msg (morse_symbol_t s) +cw_to_symbol_impl::send_symbol_msg(morse_symbol_t s) { if (s == MORSE_S_SPACE || s == MORSE_L_SPACE) { d_prev_space_symbol = true; @@ -161,11 +159,11 @@ cw_to_symbol_impl::send_symbol_msg (morse_symbol_t s) else { d_prev_space_symbol = false; } - message_port_pub (pmt::mp ("out"), pmt::from_long (s)); + message_port_pub(pmt::mp("out"), pmt::from_long(s)); } inline bool -cw_to_symbol_impl::check_conf_level (size_t cnt, size_t target) +cw_to_symbol_impl::check_conf_level(size_t cnt, size_t target) { return ((float) cnt > target * d_confidence_level); } @@ -173,15 +171,15 @@ cw_to_symbol_impl::check_conf_level (size_t cnt, size_t target) /* * Our virtual destructor. */ -cw_to_symbol_impl::~cw_to_symbol_impl () +cw_to_symbol_impl::~cw_to_symbol_impl() { - volk_free (d_const_val); - volk_free (d_tmp); - volk_free (d_out); + volk_free(d_const_val); + volk_free(d_tmp); + volk_free(d_out); } inline void -cw_to_symbol_impl::set_idle () +cw_to_symbol_impl::set_idle() { d_dec_state = NO_SYNC; d_window_cnt = 0; @@ -189,42 +187,42 @@ cw_to_symbol_impl::set_idle () } inline void -cw_to_symbol_impl::set_short_on () +cw_to_symbol_impl::set_short_on() { d_dec_state = SEARCH_DOT; d_window_cnt = 1; } inline void -cw_to_symbol_impl::set_long_on () +cw_to_symbol_impl::set_long_on() { d_dec_state = SEARCH_DASH; } inline void -cw_to_symbol_impl::set_search_space () +cw_to_symbol_impl::set_search_space() { d_dec_state = SEARCH_SPACE; d_window_cnt = 1; } void -cw_to_symbol_impl::set_act_threshold_msg_handler (pmt::pmt_t msg) +cw_to_symbol_impl::set_act_threshold_msg_handler(pmt::pmt_t msg) { - if (pmt::is_pair (msg)) { - set_act_threshold (pmt::to_double (pmt::cdr (msg))); + if (pmt::is_pair(msg)) { + set_act_threshold(pmt::to_double(pmt::cdr(msg))); } } int -cw_to_symbol_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +cw_to_symbol_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { bool triggered; size_t i; const float *in_old = (const float *) input_items[0]; - const float *in = in_old + history () - 1; + const float *in = in_old + history() - 1; if (noutput_items < 0) { return noutput_items; @@ -237,16 +235,16 @@ cw_to_symbol_impl::work (int noutput_items, * Clamp the input so the window mean is not affected by strong spikes * Good luck understanding this black magic shit! */ - triggered = is_triggered (in_old + i, d_window_size); + triggered = is_triggered(in_old + i, d_window_size); if (triggered) { LOG_DEBUG("Triggered!"); - set_short_on (); + set_short_on(); return i + 1; } } d_idle_cnt += noutput_items / d_window_size; - if(d_idle_cnt > 10 * d_long_pause_windows_num) { - send_symbol_msg (MORSE_END_MSG_SPACE); + if (d_idle_cnt > 10 * d_long_pause_windows_num) { + send_symbol_msg(MORSE_END_MSG_SPACE); d_idle_cnt = 0; } return noutput_items; @@ -254,70 +252,69 @@ cw_to_symbol_impl::work (int noutput_items, /* From now one, we handle the input in multiples of a window */ for (i = 0; i < (size_t) noutput_items / d_window_size; i++) { - triggered = is_triggered (in + i * d_window_size, d_window_size); - switch (d_dec_state) - { - case SEARCH_DOT: - if (triggered) { - d_window_cnt++; - if (d_window_cnt > d_dot_windows_num) { - set_long_on (); - LOG_DEBUG("Going to search for long sequence"); - } + triggered = is_triggered(in + i * d_window_size, d_window_size); + switch (d_dec_state) { + case SEARCH_DOT: + if (triggered) { + d_window_cnt++; + if (d_window_cnt > d_dot_windows_num) { + set_long_on(); + LOG_DEBUG("Going to search for long sequence"); } - else { - if (check_conf_level (d_window_cnt, d_dot_windows_num)) { - LOG_DEBUG("DOT"); - send_symbol_msg (MORSE_DOT); - } - LOG_DEBUG("Going to search for space: win cnt %lu", d_window_cnt); - set_search_space (); - } - break; - case SEARCH_DASH: - if (triggered) { - d_window_cnt++; - } - else { - if (check_conf_level (d_window_cnt, d_dash_windows_num)) { - LOG_DEBUG("DASH"); - send_symbol_msg (MORSE_DASH); - } - else { - LOG_DEBUG("DOT"); - send_symbol_msg (MORSE_DOT); - } - set_search_space (); - LOG_DEBUG("Going to search for space"); - } - break; - case SEARCH_SPACE: - if (triggered) { - if (check_conf_level (d_window_cnt, d_long_pause_windows_num)) { - LOG_DEBUG("LONG SPACE"); - send_symbol_msg (MORSE_L_SPACE); - } - else if (check_conf_level (d_window_cnt, d_short_pause_windows_num)) { - LOG_DEBUG("SHORT SPACE"); - send_symbol_msg (MORSE_S_SPACE); - } - set_short_on (); - LOG_DEBUG("Going to search for dot"); - } - else { - d_window_cnt++; - if (d_window_cnt > d_long_pause_windows_num) { - LOG_DEBUG("LONG SPACE"); - send_symbol_msg (MORSE_L_SPACE); - set_idle (); - LOG_DEBUG("Going to idle"); - return (i + 1) * d_window_size; - } - } - break; - default: - LOG_ERROR("Invalid decoder state"); } + else { + if (check_conf_level(d_window_cnt, d_dot_windows_num)) { + LOG_DEBUG("DOT"); + send_symbol_msg(MORSE_DOT); + } + LOG_DEBUG("Going to search for space: win cnt %lu", d_window_cnt); + set_search_space(); + } + break; + case SEARCH_DASH: + if (triggered) { + d_window_cnt++; + } + else { + if (check_conf_level(d_window_cnt, d_dash_windows_num)) { + LOG_DEBUG("DASH"); + send_symbol_msg(MORSE_DASH); + } + else { + LOG_DEBUG("DOT"); + send_symbol_msg(MORSE_DOT); + } + set_search_space(); + LOG_DEBUG("Going to search for space"); + } + break; + case SEARCH_SPACE: + if (triggered) { + if (check_conf_level(d_window_cnt, d_long_pause_windows_num)) { + LOG_DEBUG("LONG SPACE"); + send_symbol_msg(MORSE_L_SPACE); + } + else if (check_conf_level(d_window_cnt, d_short_pause_windows_num)) { + LOG_DEBUG("SHORT SPACE"); + send_symbol_msg(MORSE_S_SPACE); + } + set_short_on(); + LOG_DEBUG("Going to search for dot"); + } + else { + d_window_cnt++; + if (d_window_cnt > d_long_pause_windows_num) { + LOG_DEBUG("LONG SPACE"); + send_symbol_msg(MORSE_L_SPACE); + set_idle(); + LOG_DEBUG("Going to idle"); + return (i + 1) * d_window_size; + } + } + break; + default: + LOG_ERROR("Invalid decoder state"); + } } return i * d_window_size; } @@ -327,7 +324,7 @@ cw_to_symbol_impl::work (int noutput_items, * @param thrhld the new threshold. */ void -cw_to_symbol_impl::set_act_threshold (float thrhld) +cw_to_symbol_impl::set_act_threshold(float thrhld) { d_act_thrshld = thrhld; } @@ -341,14 +338,14 @@ cw_to_symbol_impl::set_act_threshold (float thrhld) * @param len number of samples to process */ inline void -cw_to_symbol_impl::clamp_input (int32_t* out, const float* in, size_t len) +cw_to_symbol_impl::clamp_input(int32_t *out, const float *in, size_t len) { - volk_32f_x2_subtract_32f (d_tmp, in, d_const_val, len); - volk_32f_binary_slicer_32i (d_out, d_tmp, len); + volk_32f_x2_subtract_32f(d_tmp, in, d_const_val, len); + volk_32f_binary_slicer_32i(d_out, d_tmp, len); } static inline int32_t -hadd (const int32_t* in, size_t len) +hadd(const int32_t *in, size_t len) { size_t i; int32_t cnt = 0; @@ -359,12 +356,12 @@ hadd (const int32_t* in, size_t len) } inline bool -cw_to_symbol_impl::is_triggered (const float* in, size_t len) +cw_to_symbol_impl::is_triggered(const float *in, size_t len) { int32_t cnt; - clamp_input (d_out, in, len); - cnt = hadd (d_out, len); - return (cnt >= (int32_t) (d_window_size * d_confidence_level)) ? true : false; + clamp_input(d_out, in, len); + cnt = hadd(d_out, len); + return (cnt >= (int32_t)(d_window_size * d_confidence_level)) ? true : false; } } /* namespace satnogs */ diff --git a/lib/cw_to_symbol_impl.h b/lib/cw_to_symbol_impl.h index e2fd13b..5101acb 100644 --- a/lib/cw_to_symbol_impl.h +++ b/lib/cw_to_symbol_impl.h @@ -25,79 +25,75 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class cw_to_symbol_impl : public cw_to_symbol - { +class cw_to_symbol_impl : public cw_to_symbol { - typedef enum - { - NO_SYNC, SEARCH_DOT, SEARCH_DASH, SEARCH_SPACE - } cw_dec_state_t; + typedef enum { + NO_SYNC, SEARCH_DOT, SEARCH_DASH, SEARCH_SPACE + } cw_dec_state_t; - private: - const double d_sampling_rate; - float d_act_thrshld; - const float d_confidence_level; - size_t d_dot_samples; - size_t d_window_size; - size_t d_window_cnt; - size_t d_idle_cnt; - size_t d_dot_windows_num; - size_t d_dash_windows_num; - size_t d_short_pause_windows_num; - size_t d_long_pause_windows_num; - cw_dec_state_t d_dec_state; - bool d_prev_space_symbol; - float *d_const_val; - float *d_tmp; - int32_t *d_out; +private: + const double d_sampling_rate; + float d_act_thrshld; + const float d_confidence_level; + size_t d_dot_samples; + size_t d_window_size; + size_t d_window_cnt; + size_t d_idle_cnt; + size_t d_dot_windows_num; + size_t d_dash_windows_num; + size_t d_short_pause_windows_num; + size_t d_long_pause_windows_num; + cw_dec_state_t d_dec_state; + bool d_prev_space_symbol; + float *d_const_val; + float *d_tmp; + int32_t *d_out; - inline void - set_idle (); + inline void + set_idle(); - inline void - set_short_on (); + inline void + set_short_on(); - inline void - set_long_on (); + inline void + set_long_on(); - inline void - set_search_space (); + inline void + set_search_space(); - inline void - clamp_input (int32_t *out, const float *in, size_t len); + inline void + clamp_input(int32_t *out, const float *in, size_t len); - inline bool - is_triggered (const float *in, size_t len); + inline bool + is_triggered(const float *in, size_t len); - inline void - send_symbol_msg (morse_symbol_t s); + inline void + send_symbol_msg(morse_symbol_t s); - inline bool - check_conf_level(size_t cnt, size_t target); + inline bool + check_conf_level(size_t cnt, size_t target); - void - set_act_threshold_msg_handler (pmt::pmt_t msg); + void + set_act_threshold_msg_handler(pmt::pmt_t msg); - public: - cw_to_symbol_impl (double sampling_rate, float threshold, - float conf_level, size_t wpm, size_t hysteresis); - ~cw_to_symbol_impl (); +public: + cw_to_symbol_impl(double sampling_rate, float threshold, + float conf_level, size_t wpm, size_t hysteresis); + ~cw_to_symbol_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); - void - set_act_threshold (float thrhld); - }; + void + set_act_threshold(float thrhld); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_CW_TO_SYMBOL_IMPL_H */ diff --git a/lib/debug_msg_source_impl.cc b/lib/debug_msg_source_impl.cc index f80a36d..97afe8f 100644 --- a/lib/debug_msg_source_impl.cc +++ b/lib/debug_msg_source_impl.cc @@ -26,66 +26,64 @@ #include "debug_msg_source_impl.h" #include -namespace gr +namespace gr { +namespace satnogs { + +debug_msg_source::sptr +debug_msg_source::make(const std::string &msg, double delay, bool repeat) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new debug_msg_source_impl(msg, delay, repeat)); +} - debug_msg_source::sptr - debug_msg_source::make (const std::string &msg, double delay, bool repeat) - { - return gnuradio::get_initial_sptr ( - new debug_msg_source_impl (msg, delay, repeat)); +/* + * The private constructor + */ +debug_msg_source_impl::debug_msg_source_impl(const std::string &msg, + double delay, bool repeat) : + gr::block("debug_msg_source", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_buf_len(msg.length()), + d_delay(delay), + d_repeat(repeat), + d_running(true) +{ + d_buf = new uint8_t[msg.length()]; + memcpy(d_buf, msg.c_str(), msg.length()); + message_port_register_out(pmt::mp("msg")); + boost::shared_ptr ( + new boost::thread( + boost::bind(&debug_msg_source_impl::msg_sender, this))); +} + +void +debug_msg_source_impl::msg_sender() +{ + pmt::pmt_t msg = pmt::make_blob(d_buf, d_buf_len); + if (d_repeat) { + while (d_running) { + boost::this_thread::sleep_for( + boost::chrono::milliseconds((size_t)(d_delay * 1e3))); + message_port_pub(pmt::mp("msg"), msg); } + } + else { + boost::this_thread::sleep_for( + boost::chrono::milliseconds((size_t)(d_delay * 1e3))); + message_port_pub(pmt::mp("msg"), msg); + } +} - /* - * The private constructor - */ - debug_msg_source_impl::debug_msg_source_impl (const std::string &msg, - double delay, bool repeat) : - gr::block ("debug_msg_source", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_buf_len (msg.length ()), - d_delay (delay), - d_repeat (repeat), - d_running (true) - { - d_buf = new uint8_t[msg.length ()]; - memcpy (d_buf, msg.c_str (), msg.length ()); - message_port_register_out (pmt::mp ("msg")); - boost::shared_ptr ( - new boost::thread ( - boost::bind (&debug_msg_source_impl::msg_sender, this))); - } +/* + * Our virtual destructor. + */ +debug_msg_source_impl::~debug_msg_source_impl() +{ + d_running = false; + d_thread->join(); + delete[] d_buf; +} - void - debug_msg_source_impl::msg_sender () - { - pmt::pmt_t msg = pmt::make_blob (d_buf, d_buf_len); - if (d_repeat) { - while (d_running) { - boost::this_thread::sleep_for ( - boost::chrono::milliseconds ((size_t) (d_delay * 1e3))); - message_port_pub (pmt::mp ("msg"), msg); - } - } - else { - boost::this_thread::sleep_for ( - boost::chrono::milliseconds ((size_t) (d_delay * 1e3))); - message_port_pub (pmt::mp ("msg"), msg); - } - } - - /* - * Our virtual destructor. - */ - debug_msg_source_impl::~debug_msg_source_impl () - { - d_running = false; - d_thread->join (); - delete[] d_buf; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/debug_msg_source_impl.h b/lib/debug_msg_source_impl.h index 2e270d8..2c88df7 100644 --- a/lib/debug_msg_source_impl.h +++ b/lib/debug_msg_source_impl.h @@ -24,31 +24,28 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class debug_msg_source_impl : public debug_msg_source - { - private: - const size_t d_buf_len; - const double d_delay; - const bool d_repeat; - bool d_running; - boost::shared_ptr d_thread; - uint8_t *d_buf; +class debug_msg_source_impl : public debug_msg_source { +private: + const size_t d_buf_len; + const double d_delay; + const bool d_repeat; + bool d_running; + boost::shared_ptr d_thread; + uint8_t *d_buf; - void - msg_sender(); + void + msg_sender(); - public: - debug_msg_source_impl (const std::string &msg, double delay, bool repeat); - ~debug_msg_source_impl (); +public: + debug_msg_source_impl(const std::string &msg, double delay, bool repeat); + ~debug_msg_source_impl(); - }; +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DEBUG_MSG_SOURCE_IMPL_H */ diff --git a/lib/debug_msg_source_raw_impl.cc b/lib/debug_msg_source_raw_impl.cc index 65fca62..4937400 100644 --- a/lib/debug_msg_source_raw_impl.cc +++ b/lib/debug_msg_source_raw_impl.cc @@ -25,67 +25,65 @@ #include #include "debug_msg_source_raw_impl.h" -namespace gr +namespace gr { +namespace satnogs { + +debug_msg_source_raw::sptr +debug_msg_source_raw::make(const std::vector &msg, double delay, + bool repeat) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new debug_msg_source_raw_impl(msg, delay, repeat)); +} - debug_msg_source_raw::sptr - debug_msg_source_raw::make (const std::vector &msg, double delay, - bool repeat) - { - return gnuradio::get_initial_sptr ( - new debug_msg_source_raw_impl (msg, delay, repeat)); +/* + * The private constructor + */ +debug_msg_source_raw_impl::debug_msg_source_raw_impl( + const std::vector &msg, double delay, bool repeat) : + gr::block("debug_msg_source_raw", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_buf_len(msg.size()), + d_delay(delay), + d_repeat(repeat), + d_running(true) +{ + d_buf = new uint8_t[msg.size()]; + memcpy(d_buf, msg.data(), msg.size()); + message_port_register_out(pmt::mp("msg")); + boost::shared_ptr ( + new boost::thread( + boost::bind(&debug_msg_source_raw_impl::msg_sender, this))); +} + +void +debug_msg_source_raw_impl::msg_sender() +{ + pmt::pmt_t msg = pmt::make_blob(d_buf, d_buf_len); + if (d_repeat) { + while (d_running) { + boost::this_thread::sleep_for( + boost::chrono::milliseconds((size_t)(d_delay * 1e3))); + message_port_pub(pmt::mp("msg"), msg); } + } + else { + boost::this_thread::sleep_for( + boost::chrono::milliseconds((size_t)(d_delay * 1e3))); + message_port_pub(pmt::mp("msg"), msg); + } +} - /* - * The private constructor - */ - debug_msg_source_raw_impl::debug_msg_source_raw_impl ( - const std::vector &msg, double delay, bool repeat) : - gr::block ("debug_msg_source_raw", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_buf_len (msg.size ()), - d_delay (delay), - d_repeat (repeat), - d_running (true) - { - d_buf = new uint8_t[msg.size()]; - memcpy (d_buf, msg.data(), msg.size()); - message_port_register_out (pmt::mp ("msg")); - boost::shared_ptr ( - new boost::thread ( - boost::bind (&debug_msg_source_raw_impl::msg_sender, this))); - } +/* + * Our virtual destructor. + */ +debug_msg_source_raw_impl::~debug_msg_source_raw_impl() +{ + d_running = false; + d_thread->join(); + delete[] d_buf; +} - void - debug_msg_source_raw_impl::msg_sender () - { - pmt::pmt_t msg = pmt::make_blob (d_buf, d_buf_len); - if (d_repeat) { - while (d_running) { - boost::this_thread::sleep_for ( - boost::chrono::milliseconds ((size_t) (d_delay * 1e3))); - message_port_pub (pmt::mp ("msg"), msg); - } - } - else { - boost::this_thread::sleep_for ( - boost::chrono::milliseconds ((size_t) (d_delay * 1e3))); - message_port_pub (pmt::mp ("msg"), msg); - } - } - - /* - * Our virtual destructor. - */ - debug_msg_source_raw_impl::~debug_msg_source_raw_impl () - { - d_running = false; - d_thread->join (); - delete[] d_buf; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/debug_msg_source_raw_impl.h b/lib/debug_msg_source_raw_impl.h index abc4bec..9d58813 100644 --- a/lib/debug_msg_source_raw_impl.h +++ b/lib/debug_msg_source_raw_impl.h @@ -23,32 +23,29 @@ #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class debug_msg_source_raw_impl : public debug_msg_source_raw - { - private: - const size_t d_buf_len; - const double d_delay; - const bool d_repeat; - bool d_running; - boost::shared_ptr d_thread; - uint8_t *d_buf; +class debug_msg_source_raw_impl : public debug_msg_source_raw { +private: + const size_t d_buf_len; + const double d_delay; + const bool d_repeat; + bool d_running; + boost::shared_ptr d_thread; + uint8_t *d_buf; - void - msg_sender (); + void + msg_sender(); - public: - debug_msg_source_raw_impl (const std::vector &msg, double delay, - bool repeat); - ~debug_msg_source_raw_impl (); - }; +public: + debug_msg_source_raw_impl(const std::vector &msg, double delay, + bool repeat); + ~debug_msg_source_raw_impl(); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DEBUG_MSG_SOURCE_RAW_IMPL_H */ diff --git a/lib/decoder.cc b/lib/decoder.cc index e3ec362..5099070 100644 --- a/lib/decoder.cc +++ b/lib/decoder.cc @@ -25,10 +25,8 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { int decoder::base_unique_id = 1; @@ -37,7 +35,7 @@ int decoder::base_unique_id = 1; * @return the unique id of the decoder object */ int -decoder::unique_id () +decoder::unique_id() { return d_id; } @@ -68,7 +66,7 @@ decoder::max_frame_len() const } int -decoder::sizeof_input_item () const +decoder::sizeof_input_item() const { return d_sizeof_in; } diff --git a/lib/doppler_correction_cc_impl.cc b/lib/doppler_correction_cc_impl.cc index 36aebf9..309041d 100644 --- a/lib/doppler_correction_cc_impl.cc +++ b/lib/doppler_correction_cc_impl.cc @@ -27,189 +27,187 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +doppler_correction_cc::sptr +doppler_correction_cc::make(double target_freq, double sampling_rate, + size_t corrections_per_sec) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new doppler_correction_cc_impl(target_freq, sampling_rate, + corrections_per_sec)); +} - doppler_correction_cc::sptr - doppler_correction_cc::make (double target_freq, double sampling_rate, - size_t corrections_per_sec) - { - return gnuradio::get_initial_sptr ( - new doppler_correction_cc_impl (target_freq, sampling_rate, - corrections_per_sec)); +/* + * The private constructor + */ +doppler_correction_cc_impl::doppler_correction_cc_impl( + double target_freq, double sampling_rate, size_t corrections_per_sec) : + gr::sync_block("doppler_correction_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_target_freq(target_freq), + d_samp_rate(sampling_rate), + d_update_period(sampling_rate / (double) corrections_per_sec), + d_est_thrhld(7), + d_corrections_per_sec(corrections_per_sec), + d_nco(), + /* A 3-rd order polynomial curve fitting is more than enough */ + d_doppler_fit_engine(3), + d_freq_diff(0.0), + d_have_est(false), + d_freq_est_num(0), + d_corrections(0), + d_corrected_samples(0) +{ + message_port_register_in(pmt::mp("freq")); + message_port_register_in(pmt::mp("reset")); + + /* + * NOTE: + * Set the maximum number of samples to be equivalent of half a second. + * With this way we are sure that at least one frequency message + * per second will be processed. + * + * This is taken into consideration due to the fact that the work() + * and the input message handler are NOT reentrant. + */ + set_max_noutput_items(d_samp_rate / 2.0); + set_alignment(8); + + set_msg_handler( + pmt::mp("freq"), + boost::bind(&doppler_correction_cc_impl::new_freq, this, _1)); + set_msg_handler( + pmt::mp("reset"), + boost::bind(&doppler_correction_cc_impl::reset, this, _1)); + + /* Allocate the buffer that will hold the predicted frequency differences */ + d_predicted_freqs = new double[d_corrections_per_sec]; + + /* Allocate aligned memory for the NCO */ + d_nco_buff = (gr_complex *) volk_malloc( + d_update_period * sizeof(gr_complex), 32); + if (!d_nco_buff) { + throw std::runtime_error("Could not allocate NCO memory"); + } +} + +void +doppler_correction_cc_impl::new_freq(pmt::pmt_t msg) +{ + boost::mutex::scoped_lock lock(d_mutex); + double new_freq; + new_freq = pmt::to_double(msg); + d_freq_diff = new_freq - d_target_freq; + if (!d_have_est) { + d_freq_est_num++; + d_doppler_freqs.push_back( + freq_drift(nitems_written(0), d_freq_diff)); + if (d_freq_est_num > d_est_thrhld - 1) { + d_doppler_fit_engine.fit(d_doppler_freqs); + d_doppler_fit_engine.predict_freqs(d_predicted_freqs, + d_corrections_per_sec, + d_update_period); + d_have_est = true; } + } + else { + d_doppler_freqs.pop_front(); + d_doppler_freqs.push_back( + freq_drift(nitems_written(0), d_freq_diff)); - /* - * The private constructor - */ - doppler_correction_cc_impl::doppler_correction_cc_impl ( - double target_freq, double sampling_rate, size_t corrections_per_sec) : - gr::sync_block ("doppler_correction_cc", - gr::io_signature::make (1, 1, sizeof(gr_complex)), - gr::io_signature::make (1, 1, sizeof(gr_complex))), - d_target_freq (target_freq), - d_samp_rate (sampling_rate), - d_update_period (sampling_rate / (double) corrections_per_sec), - d_est_thrhld (7), - d_corrections_per_sec (corrections_per_sec), - d_nco (), - /* A 3-rd order polynomial curve fitting is more than enough */ - d_doppler_fit_engine (3), - d_freq_diff (0.0), - d_have_est (false), - d_freq_est_num (0), - d_corrections (0), - d_corrected_samples (0) - { - message_port_register_in (pmt::mp ("freq")); - message_port_register_in (pmt::mp ("reset")); + /* Fit the doppler drift based on the new estimated frequency */ + d_doppler_fit_engine.fit(d_doppler_freqs); + /* Predict the frequency differences for the near future */ + d_doppler_fit_engine.predict_freqs(d_predicted_freqs, + d_corrections_per_sec, + d_update_period); + d_corrections = 0; + } +} +void +doppler_correction_cc_impl::reset(pmt::pmt_t msg) +{ + boost::mutex::scoped_lock lock(d_mutex); + d_doppler_freqs.clear(); + d_freq_est_num = 0; + d_corrections = 0; + d_have_est = false; +} + +/* + * Our virtual destructor. + */ +doppler_correction_cc_impl::~doppler_correction_cc_impl() +{ + delete[] d_predicted_freqs; + volk_free(d_nco_buff); +} + +int +doppler_correction_cc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + int produced = 0; + size_t cnt; + + /* + * If we do not have an estimation yet, just copy the input to the output. + * Otherwise perform Doppler correction, using the fitted curve indicating + * the frequency drift. + */ + if (d_have_est) { + while (produced < noutput_items) { /* - * NOTE: - * Set the maximum number of samples to be equivalent of half a second. - * With this way we are sure that at least one frequency message - * per second will be processed. - * - * This is taken into consideration due to the fact that the work() - * and the input message handler are NOT reentrant. + * If no samples have been corrected from the current correction step + * compute and store the NCO buffer with the corresponding frequency */ - set_max_noutput_items (d_samp_rate / 2.0); - set_alignment (8); + if (d_corrected_samples == 0) { + d_nco.set_freq( + 2 * M_PI * (-d_predicted_freqs[d_corrections]) / d_samp_rate); + d_nco.sincos(d_nco_buff, d_update_period, 1.0); + d_corrections++; - set_msg_handler ( - pmt::mp ("freq"), - boost::bind (&doppler_correction_cc_impl::new_freq, this, _1)); - set_msg_handler ( - pmt::mp ("reset"), - boost::bind (&doppler_correction_cc_impl::reset, this, _1)); - - /* Allocate the buffer that will hold the predicted frequency differences */ - d_predicted_freqs = new double[d_corrections_per_sec]; - - /* Allocate aligned memory for the NCO */ - d_nco_buff = (gr_complex *) volk_malloc ( - d_update_period * sizeof(gr_complex), 32); - if (!d_nco_buff) { - throw std::runtime_error ("Could not allocate NCO memory"); - } - } - - void - doppler_correction_cc_impl::new_freq (pmt::pmt_t msg) - { - boost::mutex::scoped_lock lock (d_mutex); - double new_freq; - new_freq = pmt::to_double (msg); - d_freq_diff = new_freq - d_target_freq; - if (!d_have_est) { - d_freq_est_num++; - d_doppler_freqs.push_back ( - freq_drift (nitems_written (0), d_freq_diff)); - if (d_freq_est_num > d_est_thrhld - 1) { - d_doppler_fit_engine.fit (d_doppler_freqs); - d_doppler_fit_engine.predict_freqs (d_predicted_freqs, - d_corrections_per_sec, - d_update_period); - d_have_est = true; - } - } - else { - d_doppler_freqs.pop_front (); - d_doppler_freqs.push_back ( - freq_drift (nitems_written (0), d_freq_diff)); - - /* Fit the doppler drift based on the new estimated frequency */ - d_doppler_fit_engine.fit (d_doppler_freqs); - /* Predict the frequency differences for the near future */ - d_doppler_fit_engine.predict_freqs (d_predicted_freqs, - d_corrections_per_sec, - d_update_period); - d_corrections = 0; - } - } - - void - doppler_correction_cc_impl::reset (pmt::pmt_t msg) - { - boost::mutex::scoped_lock lock (d_mutex); - d_doppler_freqs.clear (); - d_freq_est_num = 0; - d_corrections = 0; - d_have_est = false; - } - - /* - * Our virtual destructor. - */ - doppler_correction_cc_impl::~doppler_correction_cc_impl () - { - delete[] d_predicted_freqs; - volk_free (d_nco_buff); - } - - int - doppler_correction_cc_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - int produced = 0; - size_t cnt; - - /* - * If we do not have an estimation yet, just copy the input to the output. - * Otherwise perform Doppler correction, using the fitted curve indicating - * the frequency drift. - */ - if (d_have_est) { - while (produced < noutput_items) { - /* - * If no samples have been corrected from the current correction step - * compute and store the NCO buffer with the corresponding frequency - */ - if (d_corrected_samples == 0) { - d_nco.set_freq ( - 2 * M_PI * (-d_predicted_freqs[d_corrections]) / d_samp_rate); - d_nco.sincos (d_nco_buff, d_update_period, 1.0); - d_corrections++; - - /* - * The doppler estimation may fail/delay. In such a case the block - * should continue using the predicted frequencies - */ - if (d_corrections == d_corrections_per_sec) { - d_doppler_fit_engine.predict_freqs (d_predicted_freqs, - d_corrections_per_sec, - d_update_period); - d_corrections = 0; - } - } - - cnt = std::min (d_update_period - d_corrected_samples, - (size_t) (noutput_items - produced)); - /* Perform the doppler shift correction */ - volk_32fc_x2_multiply_32fc (out + produced, in + produced, - d_nco_buff + d_corrected_samples, cnt); - - /* Make the proper advances */ - produced += (int) cnt; - d_corrected_samples += cnt; - - if (d_corrected_samples == d_update_period) { - d_corrected_samples = 0; - } - } - } - else { - memcpy (out, in, noutput_items * sizeof(gr_complex)); + /* + * The doppler estimation may fail/delay. In such a case the block + * should continue using the predicted frequencies + */ + if (d_corrections == d_corrections_per_sec) { + d_doppler_fit_engine.predict_freqs(d_predicted_freqs, + d_corrections_per_sec, + d_update_period); + d_corrections = 0; + } } - return noutput_items; - } + cnt = std::min(d_update_period - d_corrected_samples, + (size_t)(noutput_items - produced)); + /* Perform the doppler shift correction */ + volk_32fc_x2_multiply_32fc(out + produced, in + produced, + d_nco_buff + d_corrected_samples, cnt); - } /* namespace satnogs */ + /* Make the proper advances */ + produced += (int) cnt; + d_corrected_samples += cnt; + + if (d_corrected_samples == d_update_period) { + d_corrected_samples = 0; + } + } + } + else { + memcpy(out, in, noutput_items * sizeof(gr_complex)); + } + + return noutput_items; +} + +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/doppler_correction_cc_impl.h b/lib/doppler_correction_cc_impl.h index 4cca6dc..1f708d4 100644 --- a/lib/doppler_correction_cc_impl.h +++ b/lib/doppler_correction_cc_impl.h @@ -27,50 +27,47 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class doppler_correction_cc_impl : public doppler_correction_cc - { - private: - const double d_target_freq; - const double d_samp_rate; - const size_t d_update_period; - const size_t d_est_thrhld; - const size_t d_corrections_per_sec; +class doppler_correction_cc_impl : public doppler_correction_cc { +private: + const double d_target_freq; + const double d_samp_rate; + const size_t d_update_period; + const size_t d_est_thrhld; + const size_t d_corrections_per_sec; - gr::fxpt_nco d_nco; - doppler_fit d_doppler_fit_engine; - double d_freq_diff; - bool d_have_est; - size_t d_freq_est_num; - size_t d_corrections; - size_t d_corrected_samples; - std::deque d_doppler_freqs; - double *d_predicted_freqs; - gr_complex *d_nco_buff; - boost::mutex d_mutex; + gr::fxpt_nco d_nco; + doppler_fit d_doppler_fit_engine; + double d_freq_diff; + bool d_have_est; + size_t d_freq_est_num; + size_t d_corrections; + size_t d_corrected_samples; + std::deque d_doppler_freqs; + double *d_predicted_freqs; + gr_complex *d_nco_buff; + boost::mutex d_mutex; - void - new_freq (pmt::pmt_t msg); + void + new_freq(pmt::pmt_t msg); - void - reset (pmt::pmt_t msg); + void + reset(pmt::pmt_t msg); - public: - doppler_correction_cc_impl (double target_freq, double sampling_rate, - size_t corrections_per_sec); - ~doppler_correction_cc_impl (); +public: + doppler_correction_cc_impl(double target_freq, double sampling_rate, + size_t corrections_per_sec); + ~doppler_correction_cc_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_DOPPLER_CORRECTION_CC_IMPL_H */ diff --git a/lib/doppler_fit.cc b/lib/doppler_fit.cc index 76a3a94..d79c5c9 100644 --- a/lib/doppler_fit.cc +++ b/lib/doppler_fit.cc @@ -27,119 +27,117 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +/** + * Creates a polynomial fitting routine. + * @param degree the degree of the polynomial + */ +doppler_fit::doppler_fit(size_t degree) : + d_degree(degree), + d_last_x(0.0) { - namespace satnogs - { +} - /** - * Creates a polynomial fitting routine. - * @param degree the degree of the polynomial - */ - doppler_fit::doppler_fit (size_t degree) : - d_degree(degree), - d_last_x(0.0) - { +/** + * This method calculates the coefficients of the polynomial that will + * be used by the predict_freqs() method to produce simulated frequency + * differences + * @param drifts the queue containing the frequency differences and the + * corresponding timings that these frequencies diffrences occured. Time is + * measured in samples since the start of the flowgraph execution. + */ +void +doppler_fit::fit(std::deque drifts) +{ + size_t i; + size_t j; + size_t s; + size_t singular; + double val; + s = drifts.size(); + + boost::numeric::ublas::matrix x_matrix(s, d_degree + 1); + boost::numeric::ublas::matrix y_matrix(s, 1); + + for (i = 0; i < s; i++) { + y_matrix(i, 0) = drifts[i].get_freq_drift(); + } + + for (i = 0; i < s; i++) { + val = 1.0; + for (j = 0; j < d_degree + 1; j++) { + x_matrix(i, j) = val; + val *= drifts[i].get_x(); } + } - /** - * This method calculates the coefficients of the polynomial that will - * be used by the predict_freqs() method to produce simulated frequency - * differences - * @param drifts the queue containing the frequency differences and the - * corresponding timings that these frequencies diffrences occured. Time is - * measured in samples since the start of the flowgraph execution. - */ - void - doppler_fit::fit (std::deque drifts) - { - size_t i; - size_t j; - size_t s; - size_t singular; - double val; - s = drifts.size(); + /* Transpose the matrix with the x values */ + boost::numeric::ublas::matrix tx_matrix( + boost::numeric::ublas::trans(x_matrix)); - boost::numeric::ublas::matrix x_matrix(s, d_degree+1); - boost::numeric::ublas::matrix y_matrix(s, 1); + boost::numeric::ublas::matrix txx_matrix( + boost::numeric::ublas::prec_prod(tx_matrix, x_matrix)); - for(i = 0; i < s; i++){ - y_matrix(i, 0) = drifts[i].get_freq_drift(); - } + boost::numeric::ublas::matrix txy_matrix( + boost::numeric::ublas::prec_prod(tx_matrix, y_matrix)); - for(i = 0; i < s; i++){ - val = 1.0; - for(j = 0; j < d_degree + 1; j++) { - x_matrix(i, j) = val; - val *= drifts[i].get_x(); - } - } + boost::numeric::ublas::permutation_matrix perm(txx_matrix.size1()); + singular = boost::numeric::ublas::lu_factorize(txx_matrix, perm); + BOOST_ASSERT(singular == 0); - /* Transpose the matrix with the x values */ - boost::numeric::ublas::matrix tx_matrix ( - boost::numeric::ublas::trans (x_matrix)); + boost::numeric::ublas::lu_substitute(txx_matrix, perm, txy_matrix); - boost::numeric::ublas::matrix txx_matrix ( - boost::numeric::ublas::prec_prod(tx_matrix, x_matrix)); + /* + * Lock the mutex to make sure that no one uses at the same time the + * coefficients + */ + boost::mutex::scoped_lock lock(d_mutex); + d_coeff = std::vector (txy_matrix.data().begin(), + txy_matrix.data().end()); + d_last_x = drifts[s - 1].get_x(); +} - boost::numeric::ublas::matrix txy_matrix ( - boost::numeric::ublas::prec_prod(tx_matrix, y_matrix)); - - boost::numeric::ublas::permutation_matrix perm(txx_matrix.size1()); - singular = boost::numeric::ublas::lu_factorize(txx_matrix, perm); - BOOST_ASSERT( singular == 0 ); - - boost::numeric::ublas::lu_substitute(txx_matrix, perm, txy_matrix); - - /* - * Lock the mutex to make sure that no one uses at the same time the - * coefficients - */ - boost::mutex::scoped_lock lock(d_mutex); - d_coeff = std::vector (txy_matrix.data().begin(), - txy_matrix.data().end()); - d_last_x = drifts[s - 1].get_x(); +/** + * Creates a number of frequency differences predictions using polynomial + * curve fitting. + * @param freqs buffer that will hold the predicted frequency differences. + * It is responsibility of the caller to provide enough memory for at most + * \p ncorrections double numbers. + * @param ncorrections the number predicted frequencies that the method + * will produce. + * @param samples_per_correction the number of samples elapsed between each + * correction. + */ +void +doppler_fit::predict_freqs(double *freqs, size_t ncorrections, + size_t samples_per_correction) +{ + size_t i; + size_t j; + double predicted_freq_diff; + double x; + double xT; + boost::mutex::scoped_lock lock(d_mutex); + for (i = 0; i < ncorrections; i++) { + predicted_freq_diff = 0.0; + xT = 1.0; + x = d_last_x + i * samples_per_correction; + for (j = 0; j < d_degree + 1; j++) { + predicted_freq_diff += d_coeff[j] * xT; + xT *= x; } + freqs[i] = predicted_freq_diff; + } - /** - * Creates a number of frequency differences predictions using polynomial - * curve fitting. - * @param freqs buffer that will hold the predicted frequency differences. - * It is responsibility of the caller to provide enough memory for at most - * \p ncorrections double numbers. - * @param ncorrections the number predicted frequencies that the method - * will produce. - * @param samples_per_correction the number of samples elapsed between each - * correction. - */ - void - doppler_fit::predict_freqs (double *freqs, size_t ncorrections, - size_t samples_per_correction) - { - size_t i; - size_t j; - double predicted_freq_diff; - double x; - double xT; - boost::mutex::scoped_lock lock(d_mutex); - for(i = 0; i < ncorrections; i++){ - predicted_freq_diff = 0.0; - xT = 1.0; - x = d_last_x + i * samples_per_correction; - for(j = 0; j < d_degree + 1; j++){ - predicted_freq_diff += d_coeff[j] * xT; - xT *= x; - } - freqs[i] = predicted_freq_diff; - } + /* + * The predict method can be called multiple times without update the + * fitness of the polynomial. For this reason we alter the last x + */ + d_last_x = d_last_x + (ncorrections + 1) * samples_per_correction; +} - /* - * The predict method can be called multiple times without update the - * fitness of the polynomial. For this reason we alter the last x - */ - d_last_x = d_last_x + (ncorrections + 1) * samples_per_correction; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/frame_acquisition_impl.cc b/lib/frame_acquisition_impl.cc index d224870..fccaa27 100644 --- a/lib/frame_acquisition_impl.cc +++ b/lib/frame_acquisition_impl.cc @@ -31,69 +31,67 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { frame_acquisition::sptr -frame_acquisition::make (variant_t variant, - const std::vector& preamble, - size_t preamble_threshold, - const std::vector& sync, - size_t sync_threshold, - size_t frame_size_field_len, - size_t frame_len, - checksum_t crc, - whitening::whitening_sptr descrambler, - size_t max_frame_len) +frame_acquisition::make(variant_t variant, + const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + size_t sync_threshold, + size_t frame_size_field_len, + size_t frame_len, + checksum_t crc, + whitening::whitening_sptr descrambler, + size_t max_frame_len) { - return gnuradio::get_initial_sptr ( - new frame_acquisition_impl (variant, - preamble, - preamble_threshold, - sync, - sync_threshold, - frame_size_field_len, - frame_len, - crc, - descrambler, - max_frame_len)); + return gnuradio::get_initial_sptr( + new frame_acquisition_impl(variant, + preamble, + preamble_threshold, + sync, + sync_threshold, + frame_size_field_len, + frame_len, + crc, + descrambler, + max_frame_len)); } -frame_acquisition_impl::frame_acquisition_impl (variant_t variant, - const std::vector& preamble, - size_t preamble_threshold, - const std::vector& sync, - size_t sync_threshold, - size_t frame_size_field_len, - size_t frame_len, - checksum_t crc, - whitening::whitening_sptr descrambler, - size_t max_frame_len) : - gr::sync_block ("frame_acquisition", - gr::io_signature::make (1, 1, sizeof(uint8_t)), - gr::io_signature::make (0, 0, 0)), - d_variant(variant), - d_preamble(preamble.size() * 8), - d_preamble_shift_reg(preamble.size() * 8), - d_preamble_len(preamble.size() * 8), - d_preamble_thrsh(preamble_threshold), - d_sync(sync.size() * 8), - d_sync_shift_reg(sync.size() * 8), - d_sync_len(sync.size() * 8), - d_sync_thrsh(sync_threshold), - d_state(SEARCHING), - d_cnt(0), - d_frame_size_field_len(frame_size_field_len), - d_frame_len(frame_len), - d_max_frame_len(max_frame_len), - d_crc(crc), - d_crc_len(0), - d_whitening(descrambler) +frame_acquisition_impl::frame_acquisition_impl(variant_t variant, + const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + size_t sync_threshold, + size_t frame_size_field_len, + size_t frame_len, + checksum_t crc, + whitening::whitening_sptr descrambler, + size_t max_frame_len) : + gr::sync_block("frame_acquisition", + gr::io_signature::make(1, 1, sizeof(uint8_t)), + gr::io_signature::make(0, 0, 0)), + d_variant(variant), + d_preamble(preamble.size() * 8), + d_preamble_shift_reg(preamble.size() * 8), + d_preamble_len(preamble.size() * 8), + d_preamble_thrsh(preamble_threshold), + d_sync(sync.size() * 8), + d_sync_shift_reg(sync.size() * 8), + d_sync_len(sync.size() * 8), + d_sync_thrsh(sync_threshold), + d_state(SEARCHING), + d_cnt(0), + d_frame_size_field_len(frame_size_field_len), + d_frame_len(frame_len), + d_max_frame_len(max_frame_len), + d_crc(crc), + d_crc_len(0), + d_whitening(descrambler) { set_output_multiple(8); - for(uint8_t b : preamble) { + for (uint8_t b : preamble) { d_preamble <<= (b >> 7); d_preamble <<= ((b >> 6) & 0x1); d_preamble <<= ((b >> 5) & 0x1); @@ -103,7 +101,7 @@ frame_acquisition_impl::frame_acquisition_impl (variant_t variant, d_preamble <<= ((b >> 1) & 0x1); d_preamble <<= (b & 0x1); } - for(uint8_t b : sync) { + for (uint8_t b : sync) { d_sync <<= (b >> 7); d_sync <<= ((b >> 6) & 0x1); d_sync <<= ((b >> 5) & 0x1); @@ -116,59 +114,59 @@ frame_acquisition_impl::frame_acquisition_impl (variant_t variant, /* Parameters checking */ if (max_frame_len == 0) { - throw std::invalid_argument ( - "The maximum frame size should be at least 1 byte"); + throw std::invalid_argument( + "The maximum frame size should be at least 1 byte"); } - if(d_sync_len < 8) { + if (d_sync_len < 8) { throw std::invalid_argument("SYNC word should be at least 8 bits"); } - if(d_preamble_len < 8) { + if (d_preamble_len < 8) { throw std::invalid_argument("Preamble should be at least 8 bits"); } if (d_preamble_len < 2 * d_preamble_thrsh) { - throw std::invalid_argument ( - "Too many error bits are allowed for the preamble." - "Consider lowering the threshold"); + throw std::invalid_argument( + "Too many error bits are allowed for the preamble." + "Consider lowering the threshold"); } if (d_sync_len < 2 * d_sync_thrsh) { - throw std::invalid_argument ( - "Too many error bits are allowed for the sync word. " - "Consider lowering the threshold"); + throw std::invalid_argument( + "Too many error bits are allowed for the sync word. " + "Consider lowering the threshold"); } if (d_frame_size_field_len > 4) { - throw std::invalid_argument ("Frame length field can be up to 4 bytes"); + throw std::invalid_argument("Frame length field can be up to 4 bytes"); } if (d_frame_size_field_len == 0 && d_variant != GENERIC_CONSTANT_FRAME_LEN) { - throw std::invalid_argument ("Frame length field cannot be 0"); + throw std::invalid_argument("Frame length field cannot be 0"); } - if(d_variant == GENERIC_CONSTANT_FRAME_LEN) { + if (d_variant == GENERIC_CONSTANT_FRAME_LEN) { d_frame_size_field_len = 0; } /* Set the CRC length */ - switch(d_crc) { - case CRC16_CCITT: - d_crc_len = 2; - break; - case CRC16_CCITT_REVERSED: - d_crc_len = 2; - break; - case CRC16_IBM: - d_crc_len = 2; - break; - case CRC32: - d_crc_len = 4; - break; - default: - d_crc_len = 0; - break; + switch (d_crc) { + case CRC16_CCITT: + d_crc_len = 2; + break; + case CRC16_CCITT_REVERSED: + d_crc_len = 2; + break; + case CRC16_IBM: + d_crc_len = 2; + break; + case CRC32: + d_crc_len = 4; + break; + default: + d_crc_len = 0; + break; } d_pdu = new uint8_t[max_frame_len]; @@ -180,7 +178,7 @@ frame_acquisition_impl::frame_acquisition_impl (variant_t variant, /* * Our virtual destructor. */ -frame_acquisition_impl::~frame_acquisition_impl () +frame_acquisition_impl::~frame_acquisition_impl() { delete [] d_pdu; } @@ -188,72 +186,71 @@ frame_acquisition_impl::~frame_acquisition_impl () int -frame_acquisition_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +frame_acquisition_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const uint8_t *in = (const uint8_t *) input_items[0]; - switch(d_state) - { - case SEARCHING: - return searching_preamble(in, noutput_items); - case SEARCHING_SYNC: - return searching_sync(in, noutput_items); - case DECODING_GENERIC_FRAME_LEN: - return dec_generic_frame_len(in, noutput_items); - case DECODING_GOLAY24_FRAME_LEN: - return dec_golay24_frame_len(in, noutput_items); - case DECODING_PAYLOAD: - return decoding(in, noutput_items); - default: - return noutput_items; + switch (d_state) { + case SEARCHING: + return searching_preamble(in, noutput_items); + case SEARCHING_SYNC: + return searching_sync(in, noutput_items); + case DECODING_GENERIC_FRAME_LEN: + return dec_generic_frame_len(in, noutput_items); + case DECODING_GOLAY24_FRAME_LEN: + return dec_golay24_frame_len(in, noutput_items); + case DECODING_PAYLOAD: + return decoding(in, noutput_items); + default: + return noutput_items; } } int -frame_acquisition_impl::searching_preamble (const uint8_t* in, int len) +frame_acquisition_impl::searching_preamble(const uint8_t *in, int len) { - for(int i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { d_preamble_shift_reg <<= in[i]; shift_reg tmp = d_preamble_shift_reg ^ d_preamble; - if(tmp.count() <= d_preamble_thrsh) { + if (tmp.count() <= d_preamble_thrsh) { LOG_DEBUG("Found PREAMBLE"); d_state = SEARCHING_SYNC; d_cnt = 0; - return i+1; + return i + 1; } } return len; } int -frame_acquisition_impl::searching_sync (const uint8_t* in, int len) +frame_acquisition_impl::searching_sync(const uint8_t *in, int len) { for (int i = 0; i < len; i++) { d_sync_shift_reg <<= in[i]; shift_reg tmp = d_sync_shift_reg ^ d_sync; d_cnt++; - if (tmp.count () <= d_sync_thrsh) { + if (tmp.count() <= d_sync_thrsh) { LOG_DEBUG("Found SYNC"); - switch(d_variant) { - case GENERIC_CONSTANT_FRAME_LEN: - d_state = DECODING_PAYLOAD; - break; - case GENERIC_VAR_FRAME_LEN: - d_state = DECODING_GENERIC_FRAME_LEN; - break; - case GOLAY24_CODED_FRAME_LEN: - LOG_WARN("Found!"); - d_state = DECODING_GOLAY24_FRAME_LEN; - break; + switch (d_variant) { + case GENERIC_CONSTANT_FRAME_LEN: + d_state = DECODING_PAYLOAD; + break; + case GENERIC_VAR_FRAME_LEN: + d_state = DECODING_GENERIC_FRAME_LEN; + break; + case GOLAY24_CODED_FRAME_LEN: + LOG_WARN("Found!"); + d_state = DECODING_GOLAY24_FRAME_LEN; + break; } d_cnt = 0; return i + 1; } /* The sync word should be available by now */ - if(d_cnt > d_preamble_len * 2 + d_sync_len) { + if (d_cnt > d_preamble_len * 2 + d_sync_len) { reset(); return i + 1; } @@ -262,10 +259,10 @@ frame_acquisition_impl::searching_sync (const uint8_t* in, int len) } int -frame_acquisition_impl::dec_generic_frame_len (const uint8_t* in, int len) +frame_acquisition_impl::dec_generic_frame_len(const uint8_t *in, int len) { const int s = std::min(len / 8, (int) d_frame_size_field_len); - for(int i = 0; i < s; i++) { + for (int i = 0; i < s; i++) { uint8_t b = 0x0; b |= in[i * 8] << 7; b |= in[i * 8 + 1] << 6; @@ -278,9 +275,9 @@ frame_acquisition_impl::dec_generic_frame_len (const uint8_t* in, int len) d_frame_len <<= 8; d_frame_len |= b; d_cnt++; - if(d_cnt == d_frame_size_field_len) { + if (d_cnt == d_frame_size_field_len) { /* Most of the available modems apply whitening on the frame length too */ - if(d_whitening) { + if (d_whitening) { uint32_t descrambled = 0x0; d_whitening->descramble((uint8_t *)&descrambled, (const uint8_t *)&d_frame_len, @@ -293,7 +290,7 @@ frame_acquisition_impl::dec_generic_frame_len (const uint8_t* in, int len) LOG_DEBUG("Found frame length: %u", d_frame_len); /* Length field is needed for the CRC calculation */ - for(uint32_t j = 0; j < d_frame_size_field_len; j++) { + for (uint32_t j = 0; j < d_frame_size_field_len; j++) { d_pdu[j] = (d_frame_len >> ((d_frame_size_field_len - 1 - j) * 8)) & 0xFF; } d_frame_len += d_frame_size_field_len; @@ -301,10 +298,10 @@ frame_acquisition_impl::dec_generic_frame_len (const uint8_t* in, int len) /* Append the CRC length if any */ d_frame_len += d_crc_len; - if(d_frame_len < d_max_frame_len) { + if (d_frame_len < d_max_frame_len) { d_state = DECODING_PAYLOAD; } - else{ + else { reset(); return (i + 1) * 8; } @@ -316,12 +313,12 @@ frame_acquisition_impl::dec_generic_frame_len (const uint8_t* in, int len) } int -frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len) +frame_acquisition_impl::dec_golay24_frame_len(const uint8_t *in, int len) { /* Golay24 needs 3 bytes to decode */ const int s = std::min(len / 8, 3); d_frame_len = 0; - for(int i = 0; i < s; i++) { + for (int i = 0; i < s; i++) { uint8_t b = 0x0; b |= in[i * 8] << 7; b |= in[i * 8 + 1] << 6; @@ -338,16 +335,16 @@ frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len) /* Try to decode the frame length */ if (d_cnt == 3) { LOG_WARN("Len coded %u", d_frame_len); - if(d_whitening) { + if (d_whitening) { uint32_t descrambled = 0x0; d_whitening->descramble((uint8_t *) &descrambled, (const uint8_t *)&d_frame_len, 3, false); d_frame_len = descrambled; } d_frame_len = ((d_frame_len & 0xFFF) << 12) | (d_frame_len >> 12); - golay24 g = golay24 (); + golay24 g = golay24(); uint32_t tmp = 0; - if (g.decode24 (&tmp, d_frame_len)) { + if (g.decode24(&tmp, d_frame_len)) { d_frame_len = tmp >> 12; LOG_WARN("Len %u", d_frame_len); @@ -355,16 +352,16 @@ frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len) d_frame_len += d_crc_len; /* Check if the payload can fit in the buffer */ - if(d_frame_len > d_max_frame_len) { + if (d_frame_len > d_max_frame_len) { reset(); return (i + 1) * 8; } - else{ + else { d_state = DECODING_PAYLOAD; } } else { - reset (); + reset(); return (i + 1) * 8; } d_cnt = 0; @@ -375,10 +372,10 @@ frame_acquisition_impl::dec_golay24_frame_len (const uint8_t* in, int len) } int -frame_acquisition_impl::decoding (const uint8_t* in, int len) +frame_acquisition_impl::decoding(const uint8_t *in, int len) { const int s = len / 8; - for(int i = 0; i < s; i++) { + for (int i = 0; i < s; i++) { uint8_t b = 0x0; b = in[i * 8] << 7; b |= in[i * 8 + 1] << 6; @@ -389,30 +386,30 @@ frame_acquisition_impl::decoding (const uint8_t* in, int len) b |= in[i * 8 + 6] << 1; b |= in[i * 8 + 7]; d_pdu[d_cnt++] = b; - if(d_cnt == d_frame_len) { - if(d_whitening) { + if (d_cnt == d_frame_len) { + if (d_whitening) { d_whitening->descramble(d_pdu + d_frame_size_field_len, d_pdu + d_frame_size_field_len, d_frame_len - d_frame_size_field_len, false); } - if (check_crc ()) { - message_port_pub ( - pmt::mp ("out"), - pmt::make_blob (d_pdu + d_frame_size_field_len, - d_frame_len - d_crc_len - d_frame_size_field_len)); + if (check_crc()) { + message_port_pub( + pmt::mp("out"), + pmt::make_blob(d_pdu + d_frame_size_field_len, + d_frame_len - d_crc_len - d_frame_size_field_len)); } reset(); - return (i+1) * 8; + return (i + 1) * 8; } } return len; } void -frame_acquisition_impl::reset () +frame_acquisition_impl::reset() { - if(d_whitening) { + if (d_whitening) { d_whitening->reset(); } d_cnt = 0; @@ -422,52 +419,52 @@ frame_acquisition_impl::reset () } bool -frame_acquisition_impl::check_crc () +frame_acquisition_impl::check_crc() { uint16_t crc16_c; uint16_t crc16_received; uint32_t crc32_c; uint32_t crc32_received; - switch(d_crc){ - case CRC_NONE: + switch (d_crc) { + case CRC_NONE: + return true; + case CRC16_CCITT: + crc16_c = crc16_ccitt(d_pdu, d_frame_len - 2); + memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2); + crc16_received = ntohs(crc16_received); + LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); + if (crc16_c == crc16_received) { return true; - case CRC16_CCITT: - crc16_c = crc16_ccitt(d_pdu, d_frame_len - 2); - memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2); - crc16_received = ntohs(crc16_received); - LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); - if(crc16_c == crc16_received) { - return true; - } - return false; - case CRC16_CCITT_REVERSED: - crc16_c = crc16_ccitt_reversed(d_pdu, d_frame_len - 2); - memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2); - crc16_received = ntohs(crc16_received); - LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); - if(crc16_c == crc16_received) { - return true; - } - return false; - case CRC16_IBM: - crc16_c = crc16_ibm(d_pdu, d_frame_len - 2); - memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2); - crc16_received = ntohs(crc16_received); - LOG_WARN("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); - if(crc16_c == crc16_received) { - return true; - } - return false; - case CRC32: - crc32_c = crc32(d_pdu, d_frame_len - 4); - memcpy(&crc32_received, d_pdu + d_frame_len - 4, 4); - crc32_received = ntohl(crc32_received); - if(crc32_c == crc32_received) { - return true; - } - return false; - default: - return false; + } + return false; + case CRC16_CCITT_REVERSED: + crc16_c = crc16_ccitt_reversed(d_pdu, d_frame_len - 2); + memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2); + crc16_received = ntohs(crc16_received); + LOG_DEBUG("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); + if (crc16_c == crc16_received) { + return true; + } + return false; + case CRC16_IBM: + crc16_c = crc16_ibm(d_pdu, d_frame_len - 2); + memcpy(&crc16_received, d_pdu + d_frame_len - 2, 2); + crc16_received = ntohs(crc16_received); + LOG_WARN("Received: 0x%02x Computed: 0x%02x", crc16_received, crc16_c); + if (crc16_c == crc16_received) { + return true; + } + return false; + case CRC32: + crc32_c = crc32(d_pdu, d_frame_len - 4); + memcpy(&crc32_received, d_pdu + d_frame_len - 4, 4); + crc32_received = ntohl(crc32_received); + if (crc32_c == crc32_received) { + return true; + } + return false; + default: + return false; } } diff --git a/lib/frame_acquisition_impl.h b/lib/frame_acquisition_impl.h index fd1b907..97890c2 100644 --- a/lib/frame_acquisition_impl.h +++ b/lib/frame_acquisition_impl.h @@ -24,39 +24,35 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class frame_acquisition_impl : public frame_acquisition -{ +class frame_acquisition_impl : public frame_acquisition { public: - frame_acquisition_impl (variant_t variant, - const std::vector& preamble, - size_t preamble_threshold, - const std::vector& sync, - size_t sync_threshold, - size_t frame_size_field_len, - size_t frame_len, - checksum_t crc, - whitening::whitening_sptr descrambler, - size_t max_frame_len); + frame_acquisition_impl(variant_t variant, + const std::vector &preamble, + size_t preamble_threshold, + const std::vector &sync, + size_t sync_threshold, + size_t frame_size_field_len, + size_t frame_len, + checksum_t crc, + whitening::whitening_sptr descrambler, + size_t max_frame_len); - ~frame_acquisition_impl (); + ~frame_acquisition_impl(); // Where all the action really happens int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); private: /** * Decoding FSM */ - typedef enum - { + typedef enum { SEARCHING, //!< when searching for the start of the preamble SEARCHING_SYNC, DECODING_GENERIC_FRAME_LEN, diff --git a/lib/frame_decoder_impl.cc b/lib/frame_decoder_impl.cc index c9e31c2..a1a5544 100644 --- a/lib/frame_decoder_impl.cc +++ b/lib/frame_decoder_impl.cc @@ -25,63 +25,61 @@ #include #include "frame_decoder_impl.h" -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { frame_decoder::sptr -frame_decoder::make (decoder::decoder_sptr decoder_object, int input_size) +frame_decoder::make(decoder::decoder_sptr decoder_object, int input_size) { - return gnuradio::get_initial_sptr (new frame_decoder_impl (decoder_object, - input_size)); + return gnuradio::get_initial_sptr(new frame_decoder_impl(decoder_object, + input_size)); } /* * The private constructor */ -frame_decoder_impl::frame_decoder_impl (decoder::decoder_sptr decoder_object, - int input_size) : - gr::sync_block ("frame_decoder", - gr::io_signature::make (1, 1, input_size), - gr::io_signature::make (0, 0, 0)), - d_decoder (decoder_object) +frame_decoder_impl::frame_decoder_impl(decoder::decoder_sptr decoder_object, + int input_size) : + gr::sync_block("frame_decoder", + gr::io_signature::make(1, 1, input_size), + gr::io_signature::make(0, 0, 0)), + d_decoder(decoder_object) { - if (input_size != decoder_object->sizeof_input_item ()) { - throw std::invalid_argument ( - "frame_decoder: Size mismatch between the block input and the decoder"); + if (input_size != decoder_object->sizeof_input_item()) { + throw std::invalid_argument( + "frame_decoder: Size mismatch between the block input and the decoder"); } - message_port_register_in (pmt::mp ("reset")); - message_port_register_out (pmt::mp ("out")); + message_port_register_in(pmt::mp("reset")); + message_port_register_out(pmt::mp("out")); - set_msg_handler (pmt::mp ("reset"), - boost::bind (&frame_decoder_impl::reset, this, _1)); + set_msg_handler(pmt::mp("reset"), + boost::bind(&frame_decoder_impl::reset, this, _1)); } /* * Our virtual destructor. */ -frame_decoder_impl::~frame_decoder_impl () +frame_decoder_impl::~frame_decoder_impl() { } void -frame_decoder_impl::reset (pmt::pmt_t m) +frame_decoder_impl::reset(pmt::pmt_t m) { d_decoder->reset(); } int -frame_decoder_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +frame_decoder_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const void *in = input_items[0]; - decoder_status_t status = d_decoder->decode (in, noutput_items); + decoder_status_t status = d_decoder->decode(in, noutput_items); if (status.decode_success) { - message_port_pub (pmt::mp ("out"), status.data); + message_port_pub(pmt::mp("out"), status.data); } // Tell runtime system how many output items we produced. diff --git a/lib/frame_decoder_impl.h b/lib/frame_decoder_impl.h index 1451365..825ba61 100644 --- a/lib/frame_decoder_impl.h +++ b/lib/frame_decoder_impl.h @@ -23,22 +23,19 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class frame_decoder_impl : public frame_decoder -{ +class frame_decoder_impl : public frame_decoder { public: - frame_decoder_impl (decoder::decoder_sptr decoder_object, int input_size); - ~frame_decoder_impl (); + frame_decoder_impl(decoder::decoder_sptr decoder_object, int input_size); + ~frame_decoder_impl(); // Where all the action really happens int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); private: diff --git a/lib/frame_encoder_impl.cc b/lib/frame_encoder_impl.cc index 4c52252..bad1ce7 100644 --- a/lib/frame_encoder_impl.cc +++ b/lib/frame_encoder_impl.cc @@ -25,53 +25,51 @@ #include #include "frame_encoder_impl.h" -namespace gr +namespace gr { +namespace satnogs { + +frame_encoder::sptr +frame_encoder::make(bool append_preamble, bool ecss_encap, + const std::string &dest_addr, uint8_t dest_ssid, + const std::string &src_addr, uint8_t src_ssid) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new frame_encoder_impl(append_preamble, ecss_encap, dest_addr, + dest_ssid, src_addr, src_ssid)); +} - frame_encoder::sptr - frame_encoder::make (bool append_preamble, bool ecss_encap, - const std::string& dest_addr, uint8_t dest_ssid, - const std::string& src_addr, uint8_t src_ssid) - { - return gnuradio::get_initial_sptr ( - new frame_encoder_impl (append_preamble, ecss_encap, dest_addr, - dest_ssid, src_addr, src_ssid)); - } +/* + * The private constructor + */ +frame_encoder_impl::frame_encoder_impl(bool append_preamble, + bool ecss_encap, + const std::string &dest_addr, + uint8_t dest_ssid, + const std::string &src_addr, + uint8_t src_ssid) : + gr::sync_block("frame_encoder", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) +{ +} - /* - * The private constructor - */ - frame_encoder_impl::frame_encoder_impl (bool append_preamble, - bool ecss_encap, - const std::string& dest_addr, - uint8_t dest_ssid, - const std::string& src_addr, - uint8_t src_ssid) : - gr::sync_block ("frame_encoder", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)) - { - } +/* + * Our virtual destructor. + */ +frame_encoder_impl::~frame_encoder_impl() +{ +} - /* - * Our virtual destructor. - */ - frame_encoder_impl::~frame_encoder_impl () - { - } +int +frame_encoder_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // Do <+signal processing+> - int - frame_encoder_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - // Do <+signal processing+> + // Tell runtime system how many output items we produced. + return noutput_items; +} - // Tell runtime system how many output items we produced. - return noutput_items; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/frame_encoder_impl.h b/lib/frame_encoder_impl.h index 1cd079a..10fed34 100644 --- a/lib/frame_encoder_impl.h +++ b/lib/frame_encoder_impl.h @@ -23,29 +23,26 @@ #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class frame_encoder_impl : public frame_encoder - { - private: - // Nothing to declare in this block. +class frame_encoder_impl : public frame_encoder { +private: + // Nothing to declare in this block. - public: - frame_encoder_impl (bool append_preamble, bool ecss_encap, - const std::string& dest_addr, uint8_t dest_ssid, - const std::string& src_addr, uint8_t src_ssid); - ~frame_encoder_impl (); +public: + frame_encoder_impl(bool append_preamble, bool ecss_encap, + const std::string &dest_addr, uint8_t dest_ssid, + const std::string &src_addr, uint8_t src_ssid); + ~frame_encoder_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_FRAME_ENCODER_IMPL_H */ diff --git a/lib/frame_file_sink_impl.cc b/lib/frame_file_sink_impl.cc index a08ab64..400a215 100644 --- a/lib/frame_file_sink_impl.cc +++ b/lib/frame_file_sink_impl.cc @@ -25,124 +25,116 @@ #include #include "frame_file_sink_impl.h" -namespace gr +namespace gr { +namespace satnogs { + +frame_file_sink::sptr +frame_file_sink::make(const std::string &prefix_name, int output_type) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new frame_file_sink_impl(prefix_name, output_type)); +} - frame_file_sink::sptr - frame_file_sink::make (const std::string& prefix_name, int output_type) - { - return gnuradio::get_initial_sptr ( - new frame_file_sink_impl (prefix_name, output_type)); +/* + * The private constructor + */ +frame_file_sink_impl::frame_file_sink_impl(const std::string &prefix_name, + int output_type) : + gr::block("frame_file_sink", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_prefix_name(prefix_name), + d_output_type(output_type), + d_filename_prev(""), + d_counter(0) +{ + message_port_register_in(pmt::mp("frame")); + set_msg_handler( + pmt::mp("frame"), + boost::bind(&frame_file_sink_impl::msg_handler_frame, this, _1)); + +} + +/* + * Our virtual destructor. + */ +frame_file_sink_impl::~frame_file_sink_impl() +{ +} + +void +frame_file_sink_impl::msg_handler_frame(pmt::pmt_t msg) +{ + + /* check for the current UTC time */ + std::chrono::system_clock::time_point p2 = + std::chrono::system_clock::now(); + + char buffer[30]; + std::time_t t2 = std::chrono::system_clock::to_time_t (p2); + struct tm *timeinfo; + timeinfo = std::gmtime(&t2); + + std::strftime(buffer, 30, "%FT%H-%M-%S", timeinfo); + //puts (buffer); + + /* create name of the file according prefix and timestamp */ + std::string filename; + filename.append(d_prefix_name); + filename.append("_"); + filename.append(buffer); + + + if (filename.compare(d_filename_prev) == 0) { + d_filename_prev.assign(filename); + filename.append("_"); + d_counter++; + filename.append(std::to_string(d_counter)); + } + else { + d_filename_prev.assign(filename); + d_counter = 0; + } + + uint8_t *su; + + switch (d_output_type) { + case 0: { + /* Binary form */ + std::ofstream fd(filename.c_str()); + fd.write((const char *) pmt::blob_data(msg), + pmt::blob_length(msg)); + fd.close(); + break; + } + case 1: { + /* aHex annotated, dd .txt to filename */ + filename.append(".txt"); + std::ofstream fd(filename.c_str()); + su = (uint8_t *) pmt::blob_data(msg); + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + fd << "0x" << std::hex << std::setw(2) << std::setfill('0') + << (uint32_t) su[i] << " "; } - - /* - * The private constructor - */ - frame_file_sink_impl::frame_file_sink_impl (const std::string& prefix_name, - int output_type) : - gr::block ("frame_file_sink", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_prefix_name (prefix_name), - d_output_type (output_type), - d_filename_prev(""), - d_counter(0) - { - message_port_register_in (pmt::mp ("frame")); - set_msg_handler ( - pmt::mp ("frame"), - boost::bind (&frame_file_sink_impl::msg_handler_frame, this, _1)); - + fd.close(); + break; + } + case 2: { + /* Binary annotated, add .txt to filename */ + filename.append(".txt"); + std::ofstream fd(filename.c_str()); + su = (uint8_t *) pmt::blob_data(msg); + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + fd << "0b" << std::bitset<8> (su[i]) << " "; } + fd.close(); + break; + } + default: + throw std::invalid_argument("Invalid format"); + } - /* - * Our virtual destructor. - */ - frame_file_sink_impl::~frame_file_sink_impl () - { - } +} - void - frame_file_sink_impl::msg_handler_frame (pmt::pmt_t msg) - { - - /* check for the current UTC time */ - std::chrono::system_clock::time_point p2 = - std::chrono::system_clock::now (); - - char buffer[30]; - std::time_t t2 = std::chrono::system_clock::to_time_t (p2); - struct tm * timeinfo; - timeinfo = std::gmtime (&t2); - - std::strftime (buffer, 30, "%FT%H-%M-%S", timeinfo); - //puts (buffer); - - /* create name of the file according prefix and timestamp */ - std::string filename; - filename.append (d_prefix_name); - filename.append ("_"); - filename.append (buffer); - - - if (filename.compare(d_filename_prev)==0) - { - d_filename_prev.assign(filename); - filename.append ("_"); - d_counter++; - filename.append(std::to_string(d_counter)); - } - else - { - d_filename_prev.assign(filename); - d_counter=0; - } - - uint8_t *su; - - switch (d_output_type) - { - case 0: - { - /* Binary form */ - std::ofstream fd (filename.c_str ()); - fd.write ((const char *) pmt::blob_data (msg), - pmt::blob_length (msg)); - fd.close (); - break; - } - case 1: - { - /* aHex annotated, dd .txt to filename */ - filename.append (".txt"); - std::ofstream fd (filename.c_str ()); - su = (uint8_t *) pmt::blob_data (msg); - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - fd << "0x" << std::hex << std::setw (2) << std::setfill ('0') - << (uint32_t) su[i] << " "; - } - fd.close (); - break; - } - case 2: - { - /* Binary annotated, add .txt to filename */ - filename.append (".txt"); - std::ofstream fd (filename.c_str ()); - su = (uint8_t *) pmt::blob_data (msg); - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - fd << "0b" << std::bitset<8> (su[i]) << " "; - } - fd.close (); - break; - } - default: - throw std::invalid_argument ("Invalid format"); - } - - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/frame_file_sink_impl.h b/lib/frame_file_sink_impl.h index b0e8f40..1237d04 100644 --- a/lib/frame_file_sink_impl.h +++ b/lib/frame_file_sink_impl.h @@ -26,28 +26,25 @@ #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class frame_file_sink_impl : public frame_file_sink - { - private: - const std::string d_prefix_name; - int d_output_type; - std::string d_filename_prev; - int d_counter; +class frame_file_sink_impl : public frame_file_sink { +private: + const std::string d_prefix_name; + int d_output_type; + std::string d_filename_prev; + int d_counter; - public: - frame_file_sink_impl (const std::string& prefix_name, int output_type); - ~frame_file_sink_impl (); +public: + frame_file_sink_impl(const std::string &prefix_name, int output_type); + ~frame_file_sink_impl(); - void - msg_handler_frame (pmt::pmt_t msg); - }; + void + msg_handler_frame(pmt::pmt_t msg); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_FRAME_FILE_SINK_IMPL_H */ diff --git a/lib/freq_drift.cc b/lib/freq_drift.cc index e755734..27fa0a1 100644 --- a/lib/freq_drift.cc +++ b/lib/freq_drift.cc @@ -25,45 +25,43 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +freq_drift::freq_drift(uint64_t x, double y) : + d_x(x), + d_freq_drift(y) { - namespace satnogs - { +} - freq_drift::freq_drift (uint64_t x, double y) : - d_x (x), - d_freq_drift (y) - { - } +freq_drift::~freq_drift() +{ +} - freq_drift::~freq_drift () - { - } +double +freq_drift::get_freq_drift() const +{ + return d_freq_drift; +} - double - freq_drift::get_freq_drift () const - { - return d_freq_drift; - } +void +freq_drift::set_freq_drift(double freq_drift) +{ + d_freq_drift = freq_drift; +} - void - freq_drift::set_freq_drift (double freq_drift) - { - d_freq_drift = freq_drift; - } +uint64_t +freq_drift::get_x() const +{ + return d_x; +} - uint64_t - freq_drift::get_x () const - { - return d_x; - } +void +freq_drift::set_x(uint64_t x) +{ + d_x = x; +} - void - freq_drift::set_x (uint64_t x) - { - d_x = x; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/golay24.cc b/lib/golay24.cc index c5c116a..a8201c7 100644 --- a/lib/golay24.cc +++ b/lib/golay24.cc @@ -28,10 +28,8 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { /* * Matrix P was retrieved by: @@ -40,19 +38,21 @@ namespace satnogs * Matrix mentioned by Morelos-Zaragoza, Robert H. "The art of error correcting coding." * John Wiley & Sons, 2006 was not suitable. */ -const std::vector golay24::G_P = - {0x8ED, 0x1DB, 0x3B5, 0x769, 0xED1, 0xDA3, 0xB47, 0x68F, 0xD1D, 0xA3B, 0x477, - 0xFFE}; +const std::vector golay24::G_P = { + 0x8ED, 0x1DB, 0x3B5, 0x769, 0xED1, 0xDA3, 0xB47, 0x68F, 0xD1D, 0xA3B, 0x477, + 0xFFE +}; -const std::vector golay24::G_I = - { 0x800, 0x400, 0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004, 0x002, - 0x001 }; +const std::vector golay24::G_I = { + 0x800, 0x400, 0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004, 0x002, + 0x001 +}; -golay24::golay24 () +golay24::golay24() { } -golay24::~golay24 () +golay24::~golay24() { } @@ -66,7 +66,7 @@ static inline uint32_t syndrome(uint16_t x, uint16_t y) { uint32_t s = 0; - for(size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 12; i++) { s = (s << 1) | (weight(y & golay24::G_P[i]) % 2); } s ^= x; @@ -82,10 +82,10 @@ syndrome(uint16_t x, uint16_t y) * @return the coded 24-bit message. The message is placed at the 24 LS bits */ uint32_t -golay24::encode12 (uint16_t in, bool lsb_parity) +golay24::encode12(uint16_t in, bool lsb_parity) { uint32_t c[2] = - { 0x0, 0x0 }; + { 0x0, 0x0 }; c[0] = in & 0xFFF; for (size_t i = 0; i < 12; i++) { uint32_t tmp = 0; @@ -94,7 +94,7 @@ golay24::encode12 (uint16_t in, bool lsb_parity) } c[1] = (c[1] << 1) ^ tmp; } - if(lsb_parity) { + if (lsb_parity) { return ((c[0] & 0xFFF) << 12) | (c[1] & 0xFFF); } return ((c[1] & 0xFFF) << 12) | (c[0] & 0xFFF); @@ -121,14 +121,14 @@ golay24::decode24(uint32_t *out, const uint32_t in) r[0] = (in >> 12) & 0xFFF; r[1] = in & 0xFFF; s = syndrome(r[0], r[1]); - if(weight(s) <= 3) { + if (weight(s) <= 3) { *out = ((r[0] ^ s) << 12) | (r[1]); return true; } - for(size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 12; i++) { const uint16_t tmp = s ^ G_P[i]; - if(weight(tmp) <= 2) { + if (weight(tmp) <= 2) { *out = ((r[0] ^ tmp) << 12) | (r[1] ^ G_I[i]); return true; } @@ -136,17 +136,17 @@ golay24::decode24(uint32_t *out, const uint32_t in) /* Compute the sP vector */ uint32_t sP = 0; - for(size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 12; i++) { sP = (sP << 1) | (weight(s & G_P[i]) % 2); } - if(weight(sP) == 2 || weight(sP) == 3) { + if (weight(sP) == 2 || weight(sP) == 3) { *out = (r[0] << 12) | (r[1] ^ sP); return true; } - for(size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 12; i++) { const uint16_t tmp = sP ^ G_P[i]; - if(weight(tmp) == 2) { + if (weight(tmp) == 2) { *out = ((r[0] ^ G_I[i]) << 12) | (r[1] ^ tmp); return true; } diff --git a/lib/ieee802_15_4_variant_decoder.cc b/lib/ieee802_15_4_variant_decoder.cc index 6c06743..d3d7379 100644 --- a/lib/ieee802_15_4_variant_decoder.cc +++ b/lib/ieee802_15_4_variant_decoder.cc @@ -26,19 +26,17 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -ieee802_15_4_variant_decoder::ieee802_15_4_variant_decoder ( - const std::vector &preamble, size_t preamble_threshold, - const std::vector &sync, crc::crc_t crc, - whitening::whitening_sptr descrambler) +ieee802_15_4_variant_decoder::ieee802_15_4_variant_decoder( + const std::vector &preamble, size_t preamble_threshold, + const std::vector &sync, crc::crc_t crc, + whitening::whitening_sptr descrambler) { } -ieee802_15_4_variant_decoder::~ieee802_15_4_variant_decoder () +ieee802_15_4_variant_decoder::~ieee802_15_4_variant_decoder() { } diff --git a/lib/iq_sink_impl.cc b/lib/iq_sink_impl.cc index 2e4ef76..f600d8a 100644 --- a/lib/iq_sink_impl.cc +++ b/lib/iq_sink_impl.cc @@ -27,96 +27,93 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +iq_sink::sptr +iq_sink::make(const float scale, const char *filename, bool append, + const int status) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new iq_sink_impl(scale, filename, append, status)); +} - iq_sink::sptr - iq_sink::make (const float scale, const char *filename, bool append, - const int status) +/* + * The private constructor + */ +iq_sink_impl::iq_sink_impl(const float scale, const char *filename, + bool append, const int status) : + gr::sync_block("iq_sink", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(0, 0, 0)), + file_sink_base(filename, true, append), + d_scale(scale), + d_num_points(16384), + d_status((iq_sink_status_t) status) +{ + set_max_noutput_items(d_num_points); + unsigned int alignment = volk_get_alignment(); + d_out = (int16_t *) volk_malloc(sizeof(int16_t) * d_num_points * 2, + alignment); +} + +/* + * Our virtual destructor. + */ +iq_sink_impl::~iq_sink_impl() +{ + volk_free(d_out); +} + +int +iq_sink_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *inbuf = (gr_complex *) input_items[0]; + int nwritten = 0; + switch (d_status) { + case IQ_SINK_STATUS_NULL: { + return noutput_items; + } + case IQ_SINK_STATUS_ACTIVE: { + /* update d_fp is required */ + do_update(); + + if (!d_fp) + /* drop output on the floor */ { - return gnuradio::get_initial_sptr ( - new iq_sink_impl (scale, filename, append, status)); - } - - /* - * The private constructor - */ - iq_sink_impl::iq_sink_impl (const float scale, const char *filename, - bool append, const int status) : - gr::sync_block ("iq_sink", - gr::io_signature::make (1, 1, sizeof(gr_complex)), - gr::io_signature::make (0, 0, 0)), - file_sink_base (filename, true, append), - d_scale (scale), - d_num_points (16384), - d_status ((iq_sink_status_t) status) - { - set_max_noutput_items (d_num_points); - unsigned int alignment = volk_get_alignment (); - d_out = (int16_t*) volk_malloc (sizeof(int16_t) * d_num_points * 2, - alignment); - } - - /* - * Our virtual destructor. - */ - iq_sink_impl::~iq_sink_impl () - { - volk_free (d_out); - } - - int - iq_sink_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr_complex *inbuf = (gr_complex*) input_items[0]; - int nwritten = 0; - switch (d_status) - { - case IQ_SINK_STATUS_NULL: - { - return noutput_items; - } - case IQ_SINK_STATUS_ACTIVE: - { - /* update d_fp is required */ - do_update (); - - if (!d_fp) - /* drop output on the floor */ - return noutput_items; - - volk_32f_s32f_convert_16i (d_out, (float*) inbuf, d_scale, - noutput_items * 2); - - while (nwritten < noutput_items) { - int count = fwrite (d_out, 2 * sizeof(int16_t), - noutput_items - nwritten, d_fp); - if (count == 0) { - if (ferror (d_fp)) { - std::cout << count << std::endl; - std::stringstream s; - s << "file_sink write failed with error " << fileno (d_fp) - << std::endl; - throw std::runtime_error (s.str ()); - } - /* if EOF */ - else { - break; - } - } - nwritten += count; - } - return nwritten; - } - } - /* Should never reach here */ return noutput_items; } - } /* namespace satnogs */ + volk_32f_s32f_convert_16i(d_out, (float *) inbuf, d_scale, + noutput_items * 2); + + while (nwritten < noutput_items) { + int count = fwrite(d_out, 2 * sizeof(int16_t), + noutput_items - nwritten, d_fp); + if (count == 0) { + if (ferror(d_fp)) { + std::cout << count << std::endl; + std::stringstream s; + s << "file_sink write failed with error " << fileno(d_fp) + << std::endl; + throw std::runtime_error(s.str()); + } + /* if EOF */ + else { + break; + } + } + nwritten += count; + } + return nwritten; + } + } + /* Should never reach here */ + return noutput_items; +} + +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/iq_sink_impl.h b/lib/iq_sink_impl.h index b89ff11..ff78a8c 100644 --- a/lib/iq_sink_impl.h +++ b/lib/iq_sink_impl.h @@ -25,39 +25,35 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class iq_sink_impl : public iq_sink - { - private: - /** - * The different values for iq sink status - */ - typedef enum - { - IQ_SINK_STATUS_NULL = 0, //!< IQ_SINK_STATUS_NULL IQ sink block behaves just like a null sink - IQ_SINK_STATUS_ACTIVE = 1, //!< IQ_SINK_STATUS_ACTIVE IQ sink block is active - } iq_sink_status_t; +class iq_sink_impl : public iq_sink { +private: + /** + * The different values for iq sink status + */ + typedef enum { + IQ_SINK_STATUS_NULL = 0, //!< IQ_SINK_STATUS_NULL IQ sink block behaves just like a null sink + IQ_SINK_STATUS_ACTIVE = 1, //!< IQ_SINK_STATUS_ACTIVE IQ sink block is active + } iq_sink_status_t; - iq_sink_status_t d_status; - size_t d_num_points; - float d_scale; - int16_t *d_out; + iq_sink_status_t d_status; + size_t d_num_points; + float d_scale; + int16_t *d_out; - public: - iq_sink_impl (const float scale, const char *filename, bool append, - const int status); - ~iq_sink_impl (); +public: + iq_sink_impl(const float scale, const char *filename, bool append, + const int status); + ~iq_sink_impl(); - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_IQ_SINK_IMPL_H */ diff --git a/lib/json_converter_impl.cc b/lib/json_converter_impl.cc index e26c3a0..c77b299 100644 --- a/lib/json_converter_impl.cc +++ b/lib/json_converter_impl.cc @@ -28,45 +28,43 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { json_converter::sptr -json_converter::make (const std::string& extra) +json_converter::make(const std::string &extra) { - return gnuradio::get_initial_sptr (new json_converter_impl (extra)); + return gnuradio::get_initial_sptr(new json_converter_impl(extra)); } /* * The private constructor */ -json_converter_impl::json_converter_impl (const std::string& extra) : - gr::block ("json_converter", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_extra(extra) +json_converter_impl::json_converter_impl(const std::string &extra) : + gr::block("json_converter", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_extra(extra) { message_port_register_in(pmt::mp("in")); message_port_register_out(pmt::mp("out")); - set_msg_handler (pmt::mp ("in"), - boost::bind (&json_converter_impl::convert, this, _1)); + set_msg_handler(pmt::mp("in"), + boost::bind(&json_converter_impl::convert, this, _1)); } /* * Our virtual destructor. */ -json_converter_impl::~json_converter_impl () +json_converter_impl::~json_converter_impl() { } void -json_converter_impl::convert (pmt::pmt_t m) +json_converter_impl::convert(pmt::pmt_t m) { Json::Value root = metadata::to_json(m); root["extra"] = d_extra; - const std::string& s = root.toStyledString(); + const std::string &s = root.toStyledString(); const char *c = s.c_str(); message_port_pub(pmt::mp("out"), pmt::make_blob(c, s.length())); } diff --git a/lib/json_converter_impl.h b/lib/json_converter_impl.h index b84e896..4b705e7 100644 --- a/lib/json_converter_impl.h +++ b/lib/json_converter_impl.h @@ -23,17 +23,14 @@ #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class json_converter_impl : public json_converter -{ +class json_converter_impl : public json_converter { public: - json_converter_impl (const std::string &extra); - ~json_converter_impl (); + json_converter_impl(const std::string &extra); + ~json_converter_impl(); void convert(pmt::pmt_t m); diff --git a/lib/lrpt_decoder_impl.cc b/lib/lrpt_decoder_impl.cc index e7bb7bf..0d1cace 100644 --- a/lib/lrpt_decoder_impl.cc +++ b/lib/lrpt_decoder_impl.cc @@ -29,27 +29,25 @@ extern "C" { - #include +#include } -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { lrpt_decoder::sptr -lrpt_decoder::make () +lrpt_decoder::make() { - return gnuradio::get_initial_sptr (new lrpt_decoder_impl ()); + return gnuradio::get_initial_sptr(new lrpt_decoder_impl()); } /* * The private constructor */ lrpt_decoder_impl::lrpt_decoder_impl() -: gr::block("lrpt_decoder", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)), + : gr::block("lrpt_decoder", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), /* * Metop violates the standard as many times as possible... * The frame should contain 128 RS check symbols at the end. @@ -57,7 +55,7 @@ lrpt_decoder_impl::lrpt_decoder_impl() * Thus, they dropped the check symbols at the end of the frame. */ d_cadu_len(1020 + 4 - 128), - d_coded_cadu_len(1020 * 2 + 4*2 - 128 * 2), + d_coded_cadu_len(1020 * 2 + 4 * 2 - 128 * 2), d_mpdu_max_len(59400), d_scrambler(0x2A9, 0xFF, 7), d_have_mpdu(false) @@ -65,12 +63,12 @@ lrpt_decoder_impl::lrpt_decoder_impl() message_port_register_in(pmt::mp("cadu")); message_port_register_out(pmt::mp("frame")); - set_msg_handler ( - pmt::mp ("cadu"), - boost::bind (&lrpt_decoder_impl::decode, this, _1)); + set_msg_handler( + pmt::mp("cadu"), + boost::bind(&lrpt_decoder_impl::decode, this, _1)); d_vt = create_viterbi27(d_cadu_len * 8); - if(!d_vt) { + if (!d_vt) { throw std::runtime_error("lrpt_decoder: Failed to init Viterbi decoder"); } @@ -86,7 +84,7 @@ lrpt_decoder_impl::lrpt_decoder_impl() /* * Our virtual destructor. */ -lrpt_decoder_impl::~lrpt_decoder_impl () +lrpt_decoder_impl::~lrpt_decoder_impl() { delete [] d_cadu; @@ -95,17 +93,17 @@ lrpt_decoder_impl::~lrpt_decoder_impl () } void -lrpt_decoder_impl::decode (pmt::pmt_t m) +lrpt_decoder_impl::decode(pmt::pmt_t m) { const uint8_t *coded_cadu = (const uint8_t *)pmt::blob_data(m); - if(pmt::blob_length(m) != d_coded_cadu_len) { + if (pmt::blob_length(m) != d_coded_cadu_len) { LOG_ERROR("Wrong CADU size"); return; } init_viterbi27(d_vt, 0); - for(size_t i = 0; i < d_coded_cadu_len; i++) { + for (size_t i = 0; i < d_coded_cadu_len; i++) { d_coded_cadu_syms[i * 8] = 0xFF * (coded_cadu[i] >> 7); d_coded_cadu_syms[i * 8 + 1] = 0xFF * ((coded_cadu[i] >> 6) & 0x1); d_coded_cadu_syms[i * 8 + 2] = 0xFF * ((coded_cadu[i] >> 5) & 0x1); @@ -131,10 +129,10 @@ void lrpt_decoder_impl::decode_ccsds_packet(const uint8_t *cvcdu) { /* Check first the VCDU version and if encryption is off */ - if( (cvcdu[0] >> 6) != 0x1) { + if ((cvcdu[0] >> 6) != 0x1) { return; } - if(cvcdu[6] != 0x0 || cvcdu[7] != 0x0) { + if (cvcdu[6] != 0x0 || cvcdu[7] != 0x0) { return; } @@ -147,7 +145,7 @@ lrpt_decoder_impl::decode_ccsds_packet(const uint8_t *cvcdu) /* Check CCSDS packet version and type */ //if( (mpdu[0] >> 5) != 0x0) { // return; - // } +// } uint32_t vcdu_seq = 0; vcdu_seq = cvcdu[2]; @@ -159,8 +157,8 @@ lrpt_decoder_impl::decode_ccsds_packet(const uint8_t *cvcdu) hdr_ptr = (hdr_ptr << 8) | cvcdu[9]; /* Try to find the start of a MPDU */ - if(!d_have_mpdu) { - if(hdr_ptr != 0) { + if (!d_have_mpdu) { + if (hdr_ptr != 0) { return; } d_have_mpdu = true; diff --git a/lib/lrpt_decoder_impl.h b/lib/lrpt_decoder_impl.h index 378870f..1f1aea0 100644 --- a/lib/lrpt_decoder_impl.h +++ b/lib/lrpt_decoder_impl.h @@ -25,17 +25,14 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class lrpt_decoder_impl : public lrpt_decoder -{ +class lrpt_decoder_impl : public lrpt_decoder { public: - lrpt_decoder_impl (); - ~lrpt_decoder_impl (); + lrpt_decoder_impl(); + ~lrpt_decoder_impl(); private: const size_t d_cadu_len; diff --git a/lib/lrpt_sync_impl.cc b/lib/lrpt_sync_impl.cc index 4db4c2b..10599c7 100644 --- a/lib/lrpt_sync_impl.cc +++ b/lib/lrpt_sync_impl.cc @@ -30,78 +30,76 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { lrpt_sync::sptr -lrpt_sync::make (size_t threshold) +lrpt_sync::make(size_t threshold) { - return gnuradio::get_initial_sptr (new lrpt_sync_impl (threshold)); + return gnuradio::get_initial_sptr(new lrpt_sync_impl(threshold)); } /* * The private constructor */ -lrpt_sync_impl::lrpt_sync_impl (size_t threshold) : - gr::sync_block ("lrpt_sync", - gr::io_signature::make (1, 1, sizeof(gr_complex)), - gr::io_signature::make (0, 0, 0)), - d_thresh(threshold), - d_asm_coded(0xd49c24ff2686b), - d_asm_coded_len(52), - d_asm_coded_mask((1ULL << d_asm_coded_len) - 1), - /* - * We process the data in a multiple of 2 frames and a UW - * sync word - */ - d_window((72 + 8)/2), - /* Each CADU has the 4 byte ASM and a VCDU of 1020 bytes*/ - /* - * NOTE: - * Metop violates the standard as many times as possible... - * The frame should contain 128 RS check symbols at the end. - * For some unknown reasons, it seems that the RS encoding is not performed. - * Thus, they dropped the check symbols at the end of the frame. - */ - d_coded_cadu_len(1020 * 2 + 4*2 - 128 * 2), - d_frame_sync(false), - d_received(0), - d_rotate(1.0, 0.0), - d_qpsk(digital::constellation_qpsk::make()), - d_shift_reg0(0x0), - d_shift_reg1(0x0), - d_shift_reg2(0x0), - d_shift_reg3(0x0) +lrpt_sync_impl::lrpt_sync_impl(size_t threshold) : + gr::sync_block("lrpt_sync", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(0, 0, 0)), + d_thresh(threshold), + d_asm_coded(0xd49c24ff2686b), + d_asm_coded_len(52), + d_asm_coded_mask((1ULL << d_asm_coded_len) - 1), + /* + * We process the data in a multiple of 2 frames and a UW + * sync word + */ + d_window((72 + 8) / 2), + /* Each CADU has the 4 byte ASM and a VCDU of 1020 bytes*/ + /* + * NOTE: + * Metop violates the standard as many times as possible... + * The frame should contain 128 RS check symbols at the end. + * For some unknown reasons, it seems that the RS encoding is not performed. + * Thus, they dropped the check symbols at the end of the frame. + */ + d_coded_cadu_len(1020 * 2 + 4 * 2 - 128 * 2), + d_frame_sync(false), + d_received(0), + d_rotate(1.0, 0.0), + d_qpsk(digital::constellation_qpsk::make()), + d_shift_reg0(0x0), + d_shift_reg1(0x0), + d_shift_reg2(0x0), + d_shift_reg3(0x0) { set_output_multiple(d_window); - const int alignment_multiple = volk_get_alignment () / sizeof(gr_complex); - set_alignment (std::max (1, alignment_multiple)); - d_rotate_pi2 = (gr_complex *) volk_malloc (d_window * sizeof(gr_complex), - volk_get_alignment ()); - if(!d_rotate_pi2) { + const int alignment_multiple = volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1, alignment_multiple)); + d_rotate_pi2 = (gr_complex *) volk_malloc(d_window * sizeof(gr_complex), + volk_get_alignment()); + if (!d_rotate_pi2) { throw std::runtime_error("lrpt_sync: Could not allocate memory"); } - d_rotate_2pi2 = (gr_complex *) volk_malloc (d_window * sizeof(gr_complex), - volk_get_alignment ()); - if(!d_rotate_2pi2) { + d_rotate_2pi2 = (gr_complex *) volk_malloc(d_window * sizeof(gr_complex), + volk_get_alignment()); + if (!d_rotate_2pi2) { volk_free(d_rotate_pi2); throw std::runtime_error("lrpt_sync: Could not allocate memory"); } - d_rotate_3pi2 = (gr_complex *) volk_malloc (d_window * sizeof(gr_complex), - volk_get_alignment ()); - if(!d_rotate_3pi2) { + d_rotate_3pi2 = (gr_complex *) volk_malloc(d_window * sizeof(gr_complex), + volk_get_alignment()); + if (!d_rotate_3pi2) { volk_free(d_rotate_pi2); volk_free(d_rotate_2pi2); throw std::runtime_error("lrpt_sync: Could not allocate memory"); } d_corrected = (gr_complex *)volk_malloc(d_window * sizeof(gr_complex), - volk_get_alignment ()); - if(!d_corrected) { + volk_get_alignment()); + if (!d_corrected) { volk_free(d_rotate_pi2); volk_free(d_rotate_2pi2); volk_free(d_rotate_3pi2); @@ -119,20 +117,20 @@ lrpt_sync_impl::lrpt_sync_impl (size_t threshold) : /* * Our virtual destructor. */ -lrpt_sync_impl::~lrpt_sync_impl () +lrpt_sync_impl::~lrpt_sync_impl() { - volk_free (d_rotate_pi2); - volk_free (d_rotate_2pi2); - volk_free (d_rotate_3pi2); - volk_free (d_corrected); + volk_free(d_rotate_pi2); + volk_free(d_rotate_2pi2); + volk_free(d_rotate_3pi2); + volk_free(d_corrected); delete [] d_coded_cadu; } bool lrpt_sync_impl::found_sync(uint64_t reg) { - return blocks::count_bits64 ((reg ^ d_asm_coded) & d_asm_coded_mask) - <= d_thresh; + return blocks::count_bits64((reg ^ d_asm_coded) & d_asm_coded_mask) + <= d_thresh; } @@ -141,7 +139,7 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items) { uint32_t bits; int multiple = noutput_items / d_window; - for(int i = 0; i < multiple; i++) { + for (int i = 0; i < multiple; i++) { volk_32fc_s32fc_multiply_32fc(d_rotate_pi2, in + i * d_window, gr_complex(0.0, 1.0), d_window); volk_32fc_s32fc_multiply_32fc(d_rotate_2pi2, in + i * d_window, @@ -152,11 +150,11 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items) * Search for the sync pattern, rotating the QPSK constellation on * all possible positions */ - for(int j = 0; j < d_window; j++) { + for (int j = 0; j < d_window; j++) { bits = d_qpsk->decision_maker(in + i * d_window + j); //bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1); d_shift_reg0 = (d_shift_reg0 << 2) | bits; - if(found_sync(d_shift_reg0)) { + if (found_sync(d_shift_reg0)) { d_rotate = gr_complex(1.0, 0.0); d_frame_sync = true; uint64_t asm_coded = htonll(d_shift_reg0); @@ -167,7 +165,7 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items) bits = d_qpsk->decision_maker(d_rotate_pi2 + j); //bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1); d_shift_reg1 = (d_shift_reg1 << 2) | bits; - if(found_sync(d_shift_reg1)) { + if (found_sync(d_shift_reg1)) { d_rotate = gr_complex(0.0, 1.0); d_frame_sync = true; uint64_t asm_coded = htonll(d_shift_reg1); @@ -178,7 +176,7 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items) bits = d_qpsk->decision_maker(d_rotate_2pi2 + j); //bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1); d_shift_reg2 = (d_shift_reg2 << 2) | bits; - if(found_sync(d_shift_reg2)) { + if (found_sync(d_shift_reg2)) { d_rotate = gr_complex(-1.0, 0.0); d_frame_sync = true; uint64_t asm_coded = htonll(d_shift_reg2); @@ -189,7 +187,7 @@ lrpt_sync_impl::work_no_sync(const gr_complex *in, int noutput_items) bits = d_qpsk->decision_maker(d_rotate_3pi2 + j); //bits = (d_conv_deinter.decode_bit(bits >> 1) << 1) | d_conv_deinter.decode_bit(bits & 0x1); d_shift_reg3 = (d_shift_reg3 << 2) | bits; - if(found_sync(d_shift_reg3)) { + if (found_sync(d_shift_reg3)) { d_rotate = gr_complex(0.0, -1.0); d_frame_sync = true; uint64_t asm_coded = htonll(d_shift_reg3); @@ -206,10 +204,10 @@ lrpt_sync_impl::work_sync(const gr_complex *in, int noutput_items) { uint8_t b; int multiple = noutput_items / d_window; - for(int i = 0; i < multiple; i++) { + for (int i = 0; i < multiple; i++) { volk_32fc_s32fc_multiply_32fc(d_corrected, in + i * d_window, d_rotate, d_window); - for(int j = 0; j < d_window; j += 4) { + for (int j = 0; j < d_window; j += 4) { b = 0; b = d_qpsk->decision_maker(d_corrected + j) << 6; b |= d_qpsk->decision_maker(d_corrected + j + 1) << 4; @@ -217,11 +215,11 @@ lrpt_sync_impl::work_sync(const gr_complex *in, int noutput_items) b |= d_qpsk->decision_maker(d_corrected + j + 3); d_coded_cadu[d_received++] = b; - if(d_received == d_coded_cadu_len) { + if (d_received == d_coded_cadu_len) { d_received = sizeof(uint64_t); d_frame_sync = false; - message_port_pub (pmt::mp ("cadu"), - pmt::make_blob (d_coded_cadu, d_coded_cadu_len)); + message_port_pub(pmt::mp("cadu"), + pmt::make_blob(d_coded_cadu, d_coded_cadu_len)); return i * d_window + j + 4; } } @@ -231,13 +229,13 @@ lrpt_sync_impl::work_sync(const gr_complex *in, int noutput_items) int -lrpt_sync_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +lrpt_sync_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; uint32_t bits; - if(!d_frame_sync) { + if (!d_frame_sync) { return work_no_sync(in, noutput_items); } return work_sync(in, noutput_items); diff --git a/lib/lrpt_sync_impl.h b/lib/lrpt_sync_impl.h index 516c797..8ff9479 100644 --- a/lib/lrpt_sync_impl.h +++ b/lib/lrpt_sync_impl.h @@ -25,21 +25,18 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class lrpt_sync_impl : public lrpt_sync -{ +class lrpt_sync_impl : public lrpt_sync { public: - lrpt_sync_impl (size_t threshold); - ~lrpt_sync_impl (); + lrpt_sync_impl(size_t threshold); + ~lrpt_sync_impl(); int - work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); private: const size_t d_thresh; @@ -56,11 +53,11 @@ private: uint64_t d_shift_reg1; uint64_t d_shift_reg2; uint64_t d_shift_reg3; - gr_complex* d_rotate_pi2; - gr_complex* d_rotate_2pi2; - gr_complex* d_rotate_3pi2; - gr_complex* d_corrected; - uint8_t* d_coded_cadu; + gr_complex *d_rotate_pi2; + gr_complex *d_rotate_2pi2; + gr_complex *d_rotate_3pi2; + gr_complex *d_corrected; + uint8_t *d_coded_cadu; int work_no_sync(const gr_complex *in, int noutput_items); diff --git a/lib/metadata.cc b/lib/metadata.cc index 7be2bad..da8931c 100644 --- a/lib/metadata.cc +++ b/lib/metadata.cc @@ -32,7 +32,7 @@ std::string metadata::keys() { std::string s = "["; - for(size_t i = 0; i < KEYS_NUM - 1; i++) { + for (size_t i = 0; i < KEYS_NUM - 1; i++) { s.append(value((key_t) i)); s.append(", "); } @@ -48,27 +48,27 @@ metadata::keys() * @return string corresponding to the key @a k value */ std::string -metadata::value(const key_t& k) +metadata::value(const key_t &k) { - switch(k) { - case PDU: - return "pdu"; - case CRC_VALID: - return "crc_valid"; - case FREQ_OFFSET: - return "freq_offset"; - case CORRECTED_BITS: - return "corrected_bits"; - case TIME: - return "time"; - case SAMPLE_START: - return "sample_start"; - case SAMPLE_CNT: - return "sample_cnt"; - case SYMBOL_ERASURES: - return "symbol_erasures"; - default: - throw std::invalid_argument("metadata: invalid key"); + switch (k) { + case PDU: + return "pdu"; + case CRC_VALID: + return "crc_valid"; + case FREQ_OFFSET: + return "freq_offset"; + case CORRECTED_BITS: + return "corrected_bits"; + case TIME: + return "time"; + case SAMPLE_START: + return "sample_start"; + case SAMPLE_CNT: + return "sample_cnt"; + case SYMBOL_ERASURES: + return "symbol_erasures"; + default: + throw std::invalid_argument("metadata: invalid key"); } } @@ -81,7 +81,7 @@ metadata::time_iso8601() { /* check for the current UTC time */ std::chrono::system_clock::time_point tp = - std::chrono::system_clock::now (); + std::chrono::system_clock::now(); return date::format("%FT%TZ", date::floor(tp)); } @@ -137,39 +137,39 @@ metadata::add_corrected_bits(pmt::pmt_t &m, uint32_t cnt) } Json::Value -metadata::to_json(const pmt::pmt_t& m) +metadata::to_json(const pmt::pmt_t &m) { Json::Value root; pmt::pmt_t v = pmt::dict_ref(m, pmt::mp(value(PDU)), pmt::PMT_NIL); - if(!pmt::equal(v, pmt::PMT_NIL)) { + if (!pmt::equal(v, pmt::PMT_NIL)) { uint8_t *b = (uint8_t *) pmt::blob_data(v); size_t len = pmt::blob_length(v); root[value(PDU)] = base64_encode(b, len); } v = pmt::dict_ref(m, pmt::mp(value(TIME)), pmt::PMT_NIL); - if(!pmt::equal(v, pmt::PMT_NIL)) { + if (!pmt::equal(v, pmt::PMT_NIL)) { root[value(TIME)] = pmt::symbol_to_string(v); } - v = pmt::dict_ref (m, pmt::mp (value (CRC_VALID)), pmt::PMT_NIL); - if (!pmt::equal (v, pmt::PMT_NIL)) { - root[value (CRC_VALID)] = pmt::to_bool (v); + v = pmt::dict_ref(m, pmt::mp(value(CRC_VALID)), pmt::PMT_NIL); + if (!pmt::equal(v, pmt::PMT_NIL)) { + root[value(CRC_VALID)] = pmt::to_bool(v); } - v = pmt::dict_ref (m, pmt::mp (value (SAMPLE_START)), pmt::PMT_NIL); - if (!pmt::equal (v, pmt::PMT_NIL)) { - root[value (SAMPLE_START)] = Json::Value::UInt64(pmt::to_uint64 (v)); + v = pmt::dict_ref(m, pmt::mp(value(SAMPLE_START)), pmt::PMT_NIL); + if (!pmt::equal(v, pmt::PMT_NIL)) { + root[value(SAMPLE_START)] = Json::Value::UInt64(pmt::to_uint64(v)); } - v = pmt::dict_ref (m, pmt::mp (value (SYMBOL_ERASURES)), pmt::PMT_NIL); - if (!pmt::equal (v, pmt::PMT_NIL)) { - root[value (SYMBOL_ERASURES)] = Json::Value::UInt64(pmt::to_uint64 (v)); + v = pmt::dict_ref(m, pmt::mp(value(SYMBOL_ERASURES)), pmt::PMT_NIL); + if (!pmt::equal(v, pmt::PMT_NIL)) { + root[value(SYMBOL_ERASURES)] = Json::Value::UInt64(pmt::to_uint64(v)); } - v = pmt::dict_ref (m, pmt::mp (value (CORRECTED_BITS)), pmt::PMT_NIL); - if (!pmt::equal (v, pmt::PMT_NIL)) { - root[value (CORRECTED_BITS)] = Json::Value::UInt64(pmt::to_uint64 (v)); + v = pmt::dict_ref(m, pmt::mp(value(CORRECTED_BITS)), pmt::PMT_NIL); + if (!pmt::equal(v, pmt::PMT_NIL)) { + root[value(CORRECTED_BITS)] = Json::Value::UInt64(pmt::to_uint64(v)); } return root; } diff --git a/lib/morse_debug_source_impl.cc b/lib/morse_debug_source_impl.cc index 0e8e259..133f252 100644 --- a/lib/morse_debug_source_impl.cc +++ b/lib/morse_debug_source_impl.cc @@ -28,146 +28,144 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +morse_debug_source::sptr +morse_debug_source::make(const size_t wpm, + const std::string &debug_seq, bool inject_errors, + float error_prob, + size_t seq_pause_ms) { - namespace satnogs - { - - morse_debug_source::sptr - morse_debug_source::make (const size_t wpm, - const std::string& debug_seq, bool inject_errors, - float error_prob, - size_t seq_pause_ms) - { - return gnuradio::get_initial_sptr ( - new morse_debug_source_impl (wpm, debug_seq, inject_errors, + return gnuradio::get_initial_sptr( + new morse_debug_source_impl(wpm, debug_seq, inject_errors, error_prob, seq_pause_ms)); - } +} - /* - * The private constructor - */ - morse_debug_source_impl::morse_debug_source_impl (const size_t wpm, - std::string debug_seq, - bool inject_errors, - float error_prob, - size_t seq_pause_ms) : - gr::block ("morse_debug_source", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_wpm (wpm), - d_inject_errors (inject_errors), - d_p (error_prob), - d_seq_pause_ms (seq_pause_ms), - d_run (true), - d_chars - { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', - 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }, - d_symbols - { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", - ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", - ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", - "--..", ".----", "..---", "...--", "....-", ".....", "-....", - "--...", "---..", "----.", "-----" } - { - message_port_register_out (pmt::mp ("out")); - d_thread = std::thread (&morse_debug_source_impl::send_debug_msg, this, - debug_seq); - } +/* + * The private constructor + */ +morse_debug_source_impl::morse_debug_source_impl(const size_t wpm, + std::string debug_seq, + bool inject_errors, + float error_prob, + size_t seq_pause_ms) : + gr::block("morse_debug_source", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_wpm(wpm), + d_inject_errors(inject_errors), + d_p(error_prob), + d_seq_pause_ms(seq_pause_ms), + d_run(true), + d_chars { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', + 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }, +d_symbols { + ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", + ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", + ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", + "--..", ".----", "..---", "...--", "....-", ".....", "-....", + "--...", "---..", "----.", "-----" } +{ + message_port_register_out(pmt::mp("out")); + d_thread = std::thread(&morse_debug_source_impl::send_debug_msg, this, + debug_seq); +} - static inline size_t - find_char_idx (const char* characters, size_t len, char c) - { - size_t i; - for (i = 0; i < len; i++) { - if (characters[i] == c) { - return i; - } +static inline size_t +find_char_idx(const char *characters, size_t len, char c) +{ + size_t i; + for (i = 0; i < len; i++) { + if (characters[i] == c) { + return i; + } + } + return len; +} + +void +morse_debug_source_impl::send_debug_msg(std::string sentence) +{ + size_t i; + size_t j; + size_t idx; + std::string s; + char c; + std::random_device rd; + std::mt19937 gen(rd()); + std::bernoulli_distribution error_distr(d_p); + bool inject_error; + size_t len = sentence.length(); + pmt::pmt_t port = pmt::mp("out"); + + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + while (d_run) { + /* Not the best approach, but hey, this is only for debug */ + for (i = 0; i < len; i++) { + c = std::toupper(sentence[i]); + if (c == ' ') { + message_port_pub(port, pmt::from_long(MORSE_L_SPACE)); } - return len; - } - void - morse_debug_source_impl::send_debug_msg (std::string sentence) - { - size_t i; - size_t j; - size_t idx; - std::string s; - char c; - std::random_device rd; - std::mt19937 gen (rd ()); - std::bernoulli_distribution error_distr (d_p); - bool inject_error; - size_t len = sentence.length (); - pmt::pmt_t port = pmt::mp ("out"); + idx = find_char_idx(d_chars, sizeof(d_chars), c); + if (idx != sizeof(d_chars)) { - std::this_thread::sleep_for (std::chrono::milliseconds (1000)); + s = d_symbols[idx]; + /* Get from the random distribution if an error should be injected */ + inject_error = d_inject_errors && error_distr(gen); + for (j = 0; j < s.length(); j++) { + if (s[j] == '.') { + if (inject_error) { + message_port_pub(port, pmt::from_long(MORSE_DASH)); + message_port_pub(port, pmt::from_long(MORSE_INTRA_SPACE)); - while (d_run) { - /* Not the best approach, but hey, this is only for debug */ - for (i = 0; i < len; i++) { - c = std::toupper (sentence[i]); - if (c == ' ') { - message_port_pub (port, pmt::from_long (MORSE_L_SPACE)); - } - - idx = find_char_idx (d_chars, sizeof(d_chars), c); - if (idx != sizeof(d_chars)) { - - s = d_symbols[idx]; - /* Get from the random distribution if an error should be injected */ - inject_error = d_inject_errors && error_distr (gen); - for (j = 0; j < s.length (); j++) { - if (s[j] == '.') { - if (inject_error) { - message_port_pub (port, pmt::from_long (MORSE_DASH)); - message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE)); - - } - else { - message_port_pub (port, pmt::from_long (MORSE_DOT)); - message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE)); - } - } - else { - if (inject_error) { - message_port_pub (port, pmt::from_long (MORSE_DOT)); - message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE)); - } - else { - message_port_pub (port, pmt::from_long (MORSE_DASH)); - message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE)); - } - } - std::this_thread::sleep_for (std::chrono::milliseconds (100)); } - - /* Send also a character delimiter */ - message_port_pub (port, pmt::from_long (MORSE_S_SPACE)); + else { + message_port_pub(port, pmt::from_long(MORSE_DOT)); + message_port_pub(port, pmt::from_long(MORSE_INTRA_SPACE)); + } } - } - message_port_pub (port, pmt::from_long (MORSE_L_SPACE)); - - for(i = 0; i < d_seq_pause_ms / (1200/d_wpm); i++) { - message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE)); + else { + if (inject_error) { + message_port_pub(port, pmt::from_long(MORSE_DOT)); + message_port_pub(port, pmt::from_long(MORSE_INTRA_SPACE)); + } + else { + message_port_pub(port, pmt::from_long(MORSE_DASH)); + message_port_pub(port, pmt::from_long(MORSE_INTRA_SPACE)); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - /* Perform a true sleep, to avoid message overload */ - std::this_thread::sleep_for (std::chrono::milliseconds (d_seq_pause_ms)); + /* Send also a character delimiter */ + message_port_pub(port, pmt::from_long(MORSE_S_SPACE)); } } + message_port_pub(port, pmt::from_long(MORSE_L_SPACE)); - /* - * Our virtual destructor. - */ - morse_debug_source_impl::~morse_debug_source_impl () - { - d_run = false; - d_thread.join (); + for (i = 0; i < d_seq_pause_ms / (1200 / d_wpm); i++) { + message_port_pub(port, pmt::from_long(MORSE_INTRA_SPACE)); } - } /* namespace satnogs */ + /* Perform a true sleep, to avoid message overload */ + std::this_thread::sleep_for(std::chrono::milliseconds(d_seq_pause_ms)); + } +} + +/* + * Our virtual destructor. + */ +morse_debug_source_impl::~morse_debug_source_impl() +{ + d_run = false; + d_thread.join(); +} + +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/morse_debug_source_impl.h b/lib/morse_debug_source_impl.h index 047a418..0260e37 100644 --- a/lib/morse_debug_source_impl.h +++ b/lib/morse_debug_source_impl.h @@ -27,34 +27,31 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class morse_debug_source_impl : public morse_debug_source - { - private: - const size_t d_wpm; - const bool d_inject_errors; - const float d_p; - const size_t d_seq_pause_ms; - bool d_run; - const char d_chars[36]; - const std::vector d_symbols; - std::thread d_thread; +class morse_debug_source_impl : public morse_debug_source { +private: + const size_t d_wpm; + const bool d_inject_errors; + const float d_p; + const size_t d_seq_pause_ms; + bool d_run; + const char d_chars[36]; + const std::vector d_symbols; + std::thread d_thread; - void - send_debug_msg (std::string sentence); + void + send_debug_msg(std::string sentence); - public: - morse_debug_source_impl (const size_t wpm, std::string debug_seq, - bool inject_errors, - float error_prob, size_t seq_pause_ms); - ~morse_debug_source_impl (); - }; +public: + morse_debug_source_impl(const size_t wpm, std::string debug_seq, + bool inject_errors, + float error_prob, size_t seq_pause_ms); + ~morse_debug_source_impl(); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_MORSE_DEBUG_SOURCE_IMPL_H */ diff --git a/lib/morse_decoder_impl.cc b/lib/morse_decoder_impl.cc index e54ddf8..ad890d9 100644 --- a/lib/morse_decoder_impl.cc +++ b/lib/morse_decoder_impl.cc @@ -26,77 +26,74 @@ #include #include "morse_decoder_impl.h" #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { morse_decoder::sptr -morse_decoder::make (char unrecognized_char, size_t min_frame_len) +morse_decoder::make(char unrecognized_char, size_t min_frame_len) { - return gnuradio::get_initial_sptr ( - new morse_decoder_impl (unrecognized_char, min_frame_len)); + return gnuradio::get_initial_sptr( + new morse_decoder_impl(unrecognized_char, min_frame_len)); } void -morse_decoder_impl::symbol_msg_handler (pmt::pmt_t msg) +morse_decoder_impl::symbol_msg_handler(pmt::pmt_t msg) { bool res = false; morse_symbol_t s; - s = (morse_symbol_t) pmt::to_long (msg); + s = (morse_symbol_t) pmt::to_long(msg); - switch (s) - { - case MORSE_DOT: - case MORSE_DASH: - case MORSE_S_SPACE: - res = d_morse_tree.received_symbol (s); + switch (s) { + case MORSE_DOT: + case MORSE_DASH: + case MORSE_S_SPACE: + res = d_morse_tree.received_symbol(s); + break; + /* + * If a word separator occurs it is a good time to retrieve the decoded + * word + */ + case MORSE_L_SPACE: + /* + * Inject a character separator, for the morse decoder to commit + * the outstanding character + */ + res = d_morse_tree.received_symbol(MORSE_S_SPACE); + /* Just ignore the word separator if no word is yet decoded */ + if (d_morse_tree.get_word_len() == 0) { + res = true; break; - /* - * If a word separator occurs it is a good time to retrieve the decoded - * word - */ - case MORSE_L_SPACE: - /* - * Inject a character separator, for the morse decoder to commit - * the outstanding character - */ - res = d_morse_tree.received_symbol (MORSE_S_SPACE); - /* Just ignore the word separator if no word is yet decoded */ - if (d_morse_tree.get_word_len () == 0) { - res = true; - break; - } - d_str = d_str.append(d_morse_tree.get_word ()); - d_str = d_str.append(" "); - d_morse_tree.reset (); - break; - case MORSE_INTRA_SPACE: - /*Ignore it */ - break; - case MORSE_END_MSG_SPACE: - if (d_str.length () > d_min_frame_len) { - d_morse_tree.reset (); - message_port_pub (pmt::mp ("out"), - pmt::make_blob (d_str.c_str (), d_str.length ())); - d_str = ""; - } - break; - default: - LOG_ERROR("Unknown Morse symbol"); - return; } + d_str = d_str.append(d_morse_tree.get_word()); + d_str = d_str.append(" "); + d_morse_tree.reset(); + break; + case MORSE_INTRA_SPACE: + /*Ignore it */ + break; + case MORSE_END_MSG_SPACE: + if (d_str.length() > d_min_frame_len) { + d_morse_tree.reset(); + message_port_pub(pmt::mp("out"), + pmt::make_blob(d_str.c_str(), d_str.length())); + d_str = ""; + } + break; + default: + LOG_ERROR("Unknown Morse symbol"); + return; + } /* * If the decoding return false, it means that either an non decode-able * character situation occurred or the maximum word limit reached */ if (!res) { - if (d_morse_tree.get_max_word_len () == d_morse_tree.get_word_len ()) { - d_str = d_morse_tree.get_word (); - d_morse_tree.reset (); - message_port_pub (pmt::mp ("out"), - pmt::make_blob (d_str.c_str (), d_str.length ())); + if (d_morse_tree.get_max_word_len() == d_morse_tree.get_word_len()) { + d_str = d_morse_tree.get_word(); + d_morse_tree.reset(); + message_port_pub(pmt::mp("out"), + pmt::make_blob(d_str.c_str(), d_str.length())); } } } @@ -104,21 +101,21 @@ morse_decoder_impl::symbol_msg_handler (pmt::pmt_t msg) /* * The private constructor */ -morse_decoder_impl::morse_decoder_impl (char unrecognized_char, - size_t min_frame_len) : - gr::block ("morse_decoder", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_morse_tree (unrecognized_char), - d_min_frame_len (min_frame_len), - d_str("") +morse_decoder_impl::morse_decoder_impl(char unrecognized_char, + size_t min_frame_len) : + gr::block("morse_decoder", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_morse_tree(unrecognized_char), + d_min_frame_len(min_frame_len), + d_str("") { /* Register the input and output msg handler */ - message_port_register_in (pmt::mp ("in")); - message_port_register_out (pmt::mp ("out")); - set_msg_handler ( - pmt::mp ("in"), - boost::bind (&morse_decoder_impl::symbol_msg_handler, this, _1)); + message_port_register_in(pmt::mp("in")); + message_port_register_out(pmt::mp("out")); + set_msg_handler( + pmt::mp("in"), + boost::bind(&morse_decoder_impl::symbol_msg_handler, this, _1)); } } /* namespace satnogs */ diff --git a/lib/morse_decoder_impl.h b/lib/morse_decoder_impl.h index 0eceedc..e423e8c 100644 --- a/lib/morse_decoder_impl.h +++ b/lib/morse_decoder_impl.h @@ -24,16 +24,13 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class morse_decoder_impl : public morse_decoder -{ +class morse_decoder_impl : public morse_decoder { public: - morse_decoder_impl (char unrecognized_char, size_t min_frame_len); + morse_decoder_impl(char unrecognized_char, size_t min_frame_len); private: morse_tree d_morse_tree; @@ -41,7 +38,7 @@ private: std::string d_str; void - symbol_msg_handler (pmt::pmt_t msg); + symbol_msg_handler(pmt::pmt_t msg); }; } // namespace satnogs diff --git a/lib/morse_tree.cc b/lib/morse_tree.cc index ce08a00..de5ec23 100644 --- a/lib/morse_tree.cc +++ b/lib/morse_tree.cc @@ -28,287 +28,284 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +/*! + * Constructs a Morse code tree for Morse code decoding + */ +morse_tree::morse_tree() : + d_unrecognized_symbol('#'), + d_root(new tree_node(0)), + d_current(d_root), + d_buff_len(4096), + d_word_len(0), + d_word_buffer(new char[d_buff_len]) { - namespace satnogs - { + construct_tree(); +} - /*! - * Constructs a Morse code tree for Morse code decoding +/*! + * Constructs a Morse code tree for Morse code decoding + * @param unrecognized the character that will be placed + * in the place of unrecognized symbols + */ +morse_tree::morse_tree(char unrecognized) : + d_unrecognized_symbol(unrecognized), + d_root(new tree_node(0)), + d_current(d_root), + d_buff_len(4096), + d_word_len(0), + d_word_buffer(new char[d_buff_len]) +{ + construct_tree(); +} + +morse_tree::~morse_tree() +{ + delete_tree(d_root); +} + +/*! + * Resets the pointer to the initial root node + */ +void +morse_tree::reset() +{ + d_current = d_root; + d_word_len = 0; + memset(d_word_buffer.get(), 0, d_buff_len); +} + +/*! + * Creates and initializes the Morse code decoder tree + */ +void +morse_tree::construct_tree() +{ + tree_node *e = new tree_node('E'); + tree_node *t = new tree_node('T'); + tree_node *i = new tree_node('I'); + tree_node *a = new tree_node('A'); + tree_node *n = new tree_node('N'); + tree_node *m = new tree_node('M'); + tree_node *s = new tree_node('S'); + tree_node *u = new tree_node('U'); + tree_node *r = new tree_node('R'); + tree_node *w = new tree_node('W'); + tree_node *d = new tree_node('D'); + tree_node *k = new tree_node('K'); + tree_node *g = new tree_node('G'); + tree_node *o = new tree_node('O'); + tree_node *h = new tree_node('H'); + tree_node *v = new tree_node('V'); + tree_node *f = new tree_node('F'); + tree_node *u_u = new tree_node('U'); + tree_node *l = new tree_node('L'); + tree_node *u_a = new tree_node('A'); + tree_node *p = new tree_node('P'); + tree_node *j = new tree_node('J'); + tree_node *b = new tree_node('B'); + tree_node *x = new tree_node('X'); + tree_node *c = new tree_node('C'); + tree_node *y = new tree_node('Y'); + tree_node *z = new tree_node('Z'); + tree_node *q = new tree_node('Q'); + tree_node *u_o = new tree_node('O'); + tree_node *null0 = new tree_node(0); + tree_node *n5 = new tree_node('5'); + tree_node *n4 = new tree_node('4'); + tree_node *a_s = new tree_node('S'); + tree_node *n3 = new tree_node('3'); + tree_node *a_e = new tree_node('E'); + tree_node *d_d = new tree_node('D'); + tree_node *n2 = new tree_node('2'); + tree_node *d_e = new tree_node('E'); + tree_node *plus = new tree_node('+'); + tree_node *d_a = new tree_node('A'); + tree_node *d_j = new tree_node('J'); + tree_node *n1 = new tree_node('1'); + tree_node *n6 = new tree_node('6'); + tree_node *eq = new tree_node('='); + tree_node *slash = new tree_node('/'); + tree_node *null1 = new tree_node(0); + tree_node *n7 = new tree_node('7'); + tree_node *null2 = new tree_node(0); + tree_node *n8 = new tree_node('8'); + tree_node *n9 = new tree_node('9'); + tree_node *n0 = new tree_node('0'); + + d_root->set_left_child(e); + d_root->set_right_child(t); + + e->set_left_child(i); + e->set_right_child(a); + t->set_left_child(n); + t->set_right_child(m); + + i->set_left_child(s); + i->set_right_child(u); + a->set_left_child(r); + a->set_right_child(w); + n->set_left_child(d); + n->set_right_child(k); + m->set_left_child(g); + m->set_right_child(o); + + s->set_left_child(h); + s->set_right_child(v); + u->set_left_child(f); + u->set_right_child(u_u); + r->set_left_child(l); + r->set_right_child(u_a); + w->set_left_child(p); + w->set_right_child(j); + d->set_left_child(b); + d->set_right_child(x); + k->set_left_child(c); + k->set_right_child(y); + g->set_left_child(z); + g->set_right_child(q); + o->set_left_child(u_o); + o->set_right_child(null0); + + h->set_left_child(n5); + h->set_right_child(n4); + v->set_left_child(a_s); + v->set_right_child(n3); + f->set_left_child(a_e); + u_u->set_left_child(d_d); + u_u->set_right_child(n2); + l->set_right_child(d_e); + u_a->set_left_child(plus); + p->set_right_child(d_a); + j->set_left_child(d_j); + j->set_right_child(n1); + b->set_left_child(n6); + b->set_right_child(eq); + x->set_left_child(slash); + c->set_right_child(null1); + z->set_left_child(n7); + z->set_right_child(null2); + u_o->set_left_child(n8); + null0->set_left_child(n9); + null0->set_right_child(n0); +} + +bool +morse_tree::received_symbol(morse_symbol_t s) +{ + char c = 0; + bool ret = false; + /* Check for overflow */ + if (d_word_len == d_buff_len) { + return false; + } + switch (s) { + case MORSE_DOT: + if (d_current->get_left_child()) { + d_current = d_current->get_left_child(); + ret = true; + } + break; + case MORSE_DASH: + if (d_current->get_right_child()) { + d_current = d_current->get_right_child(); + ret = true; + } + break; + case MORSE_S_SPACE: + /* + * A short space received, but the decoder is still at the root. + * This is not in general an error so we return true */ - morse_tree::morse_tree () : - d_unrecognized_symbol ('#'), - d_root (new tree_node (0)), - d_current (d_root), - d_buff_len (4096), - d_word_len (0), - d_word_buffer (new char[d_buff_len]) - { - construct_tree (); + if (d_current == d_root) { + return true; } - - /*! - * Constructs a Morse code tree for Morse code decoding - * @param unrecognized the character that will be placed - * in the place of unrecognized symbols + c = d_current->get_char(); + d_current = d_root; + /* + * Some nodes are null transitions and do not correspond to + * a specific character */ - morse_tree::morse_tree (char unrecognized) : - d_unrecognized_symbol (unrecognized), - d_root (new tree_node (0)), - d_current (d_root), - d_buff_len (4096), - d_word_len (0), - d_word_buffer (new char[d_buff_len]) - { - construct_tree (); + if (c != 0) { + d_word_buffer[d_word_len] = c; + d_word_len++; + ret = true; } + break; + default: + LOG_ERROR("Unsupported Morse symbol"); + return false; + } + return ret; +} - morse_tree::~morse_tree () - { - delete_tree(d_root); - } +std::string +morse_tree::get_word() +{ + return std::string(d_word_buffer.get(), d_word_len); +} - /*! - * Resets the pointer to the initial root node - */ - void - morse_tree::reset () - { - d_current = d_root; - d_word_len = 0; - memset(d_word_buffer.get(), 0, d_buff_len); - } +size_t +morse_tree::get_max_word_len() const +{ + return d_buff_len; +} - /*! - * Creates and initializes the Morse code decoder tree - */ - void - morse_tree::construct_tree () - { - tree_node *e = new tree_node ('E'); - tree_node *t = new tree_node ('T'); - tree_node *i = new tree_node ('I'); - tree_node *a = new tree_node ('A'); - tree_node *n = new tree_node ('N'); - tree_node *m = new tree_node ('M'); - tree_node *s = new tree_node ('S'); - tree_node *u = new tree_node ('U'); - tree_node *r = new tree_node ('R'); - tree_node *w = new tree_node ('W'); - tree_node *d = new tree_node ('D'); - tree_node *k = new tree_node ('K'); - tree_node *g = new tree_node ('G'); - tree_node *o = new tree_node ('O'); - tree_node *h = new tree_node ('H'); - tree_node *v = new tree_node ('V'); - tree_node *f = new tree_node ('F'); - tree_node *u_u = new tree_node ('U'); - tree_node *l = new tree_node ('L'); - tree_node *u_a = new tree_node ('A'); - tree_node *p = new tree_node ('P'); - tree_node *j = new tree_node ('J'); - tree_node *b = new tree_node ('B'); - tree_node *x = new tree_node ('X'); - tree_node *c = new tree_node ('C'); - tree_node *y = new tree_node ('Y'); - tree_node *z = new tree_node ('Z'); - tree_node *q = new tree_node ('Q'); - tree_node *u_o = new tree_node ('O'); - tree_node *null0 = new tree_node (0); - tree_node *n5 = new tree_node ('5'); - tree_node *n4 = new tree_node ('4'); - tree_node *a_s = new tree_node ('S'); - tree_node *n3 = new tree_node ('3'); - tree_node *a_e = new tree_node ('E'); - tree_node *d_d = new tree_node ('D'); - tree_node *n2 = new tree_node ('2'); - tree_node *d_e = new tree_node ('E'); - tree_node *plus = new tree_node ('+'); - tree_node *d_a = new tree_node ('A'); - tree_node *d_j = new tree_node ('J'); - tree_node *n1 = new tree_node ('1'); - tree_node *n6 = new tree_node ('6'); - tree_node *eq = new tree_node ('='); - tree_node *slash = new tree_node ('/'); - tree_node *null1 = new tree_node (0); - tree_node *n7 = new tree_node ('7'); - tree_node *null2 = new tree_node (0); - tree_node *n8 = new tree_node ('8'); - tree_node *n9 = new tree_node ('9'); - tree_node *n0 = new tree_node ('0'); +size_t +morse_tree::get_word_len() +{ + return d_word_len; +} - d_root->set_left_child (e); - d_root->set_right_child (t); +void +morse_tree::delete_tree(tree_node *node) +{ + if (!node) { + return; + } + delete_tree(node->get_left_child()); + delete_tree(node->get_right_child()); + delete node; +} - e->set_left_child (i); - e->set_right_child (a); - t->set_left_child (n); - t->set_right_child (m); +tree_node::tree_node(char c) : + d_char(c), + d_left(NULL), + d_right(NULL) +{ +} - i->set_left_child (s); - i->set_right_child (u); - a->set_left_child (r); - a->set_right_child (w); - n->set_left_child (d); - n->set_right_child (k); - m->set_left_child (g); - m->set_right_child (o); +void +tree_node::set_left_child(tree_node *child) +{ + d_left = child; +} - s->set_left_child (h); - s->set_right_child (v); - u->set_left_child (f); - u->set_right_child (u_u); - r->set_left_child (l); - r->set_right_child (u_a); - w->set_left_child (p); - w->set_right_child (j); - d->set_left_child (b); - d->set_right_child (x); - k->set_left_child (c); - k->set_right_child (y); - g->set_left_child (z); - g->set_right_child (q); - o->set_left_child (u_o); - o->set_right_child (null0); +void +tree_node::set_right_child(tree_node *child) +{ + d_right = child; +} - h->set_left_child (n5); - h->set_right_child (n4); - v->set_left_child (a_s); - v->set_right_child (n3); - f->set_left_child (a_e); - u_u->set_left_child (d_d); - u_u->set_right_child (n2); - l->set_right_child (d_e); - u_a->set_left_child (plus); - p->set_right_child (d_a); - j->set_left_child (d_j); - j->set_right_child (n1); - b->set_left_child (n6); - b->set_right_child (eq); - x->set_left_child (slash); - c->set_right_child (null1); - z->set_left_child (n7); - z->set_right_child (null2); - u_o->set_left_child (n8); - null0->set_left_child (n9); - null0->set_right_child (n0); - } +tree_node * +tree_node::get_left_child() +{ + return d_left; +} - bool - morse_tree::received_symbol (morse_symbol_t s) - { - char c = 0; - bool ret = false; - /* Check for overflow */ - if (d_word_len == d_buff_len) { - return false; - } - switch (s) - { - case MORSE_DOT: - if (d_current->get_left_child ()) { - d_current = d_current->get_left_child (); - ret = true; - } - break; - case MORSE_DASH: - if (d_current->get_right_child ()) { - d_current = d_current->get_right_child (); - ret = true; - } - break; - case MORSE_S_SPACE: - /* - * A short space received, but the decoder is still at the root. - * This is not in general an error so we return true - */ - if (d_current == d_root) { - return true; - } - c = d_current->get_char (); - d_current = d_root; - /* - * Some nodes are null transitions and do not correspond to - * a specific character - */ - if (c != 0) { - d_word_buffer[d_word_len] = c; - d_word_len++; - ret = true; - } - break; - default: - LOG_ERROR("Unsupported Morse symbol"); - return false; - } - return ret; - } +tree_node * +tree_node::get_right_child() +{ + return d_right; +} - std::string - morse_tree::get_word () - { - return std::string(d_word_buffer.get(), d_word_len); - } +char +tree_node::get_char() +{ + return d_char; +} - size_t - morse_tree::get_max_word_len () const - { - return d_buff_len; - } - - size_t - morse_tree::get_word_len () - { - return d_word_len; - } - - void - morse_tree::delete_tree (tree_node *node) - { - if (!node) { - return; - } - delete_tree (node->get_left_child ()); - delete_tree (node->get_right_child ()); - delete node; - } - - tree_node::tree_node (char c) : - d_char (c), - d_left (NULL), - d_right (NULL) - { - } - - void - tree_node::set_left_child (tree_node* child) - { - d_left = child; - } - - void - tree_node::set_right_child (tree_node* child) - { - d_right = child; - } - - tree_node* - tree_node::get_left_child () - { - return d_left; - } - - tree_node* - tree_node::get_right_child () - { - return d_right; - } - - char - tree_node::get_char () - { - return d_char; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/multi_format_msg_sink_impl.cc b/lib/multi_format_msg_sink_impl.cc index b4cd5df..82c6748 100644 --- a/lib/multi_format_msg_sink_impl.cc +++ b/lib/multi_format_msg_sink_impl.cc @@ -28,141 +28,137 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +multi_format_msg_sink::sptr +multi_format_msg_sink::make(size_t format, + bool timestamp, + bool out_stdout, + const std::string &filepath) { - namespace satnogs - { - - multi_format_msg_sink::sptr - multi_format_msg_sink::make (size_t format, - bool timestamp, - bool out_stdout, - const std::string& filepath) - { - return gnuradio::get_initial_sptr ( - new multi_format_msg_sink_impl (format, timestamp, + return gnuradio::get_initial_sptr( + new multi_format_msg_sink_impl(format, timestamp, out_stdout, filepath)); +} + +void +multi_format_msg_sink_impl::msg_handler_file(pmt::pmt_t msg) +{ + uint8_t *su; + char buf[256]; + std::string s((const char *) pmt::blob_data(msg), + pmt::blob_length(msg)); + + if (d_timestamp) { + std::time_t t = std::time(nullptr); + std::tm tm = *std::localtime(&t); + strftime(buf, sizeof(buf), "%F %T %z", &tm); + d_fos << "[" << buf << "]"; + } + + switch (d_format) { + case 0: + d_fos << s << std::endl; + break; + case 1: + su = (uint8_t *) pmt::blob_data(msg); + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + d_fos << "0x" << std::hex << std::setw(2) << std::setfill('0') + << (uint32_t) su[i] << " "; } + d_fos << std::endl; + break; + case 2: + su = (uint8_t *) pmt::blob_data(msg); + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + d_fos << "0b" << std::bitset<8> (su[i]) << " "; + } + d_fos << std::endl; + break; + default: + throw std::invalid_argument("Invalid format"); + } +} - void - multi_format_msg_sink_impl::msg_handler_file (pmt::pmt_t msg) - { - uint8_t *su; - char buf[256]; - std::string s ((const char *) pmt::blob_data (msg), - pmt::blob_length (msg)); +void +multi_format_msg_sink_impl::msg_handler_stdout(pmt::pmt_t msg) +{ + uint8_t *su; + char buf[256]; + std::string s((const char *) pmt::blob_data(msg), + pmt::blob_length(msg)); - if(d_timestamp) { - std::time_t t = std::time(nullptr); - std::tm tm = *std::localtime(&t); - strftime(buf, sizeof(buf), "%F %T %z", &tm); - d_fos << "[" << buf << "]"; - } + if (d_timestamp) { + std::time_t t = std::time(nullptr); + std::tm tm = *std::localtime(&t); + strftime(buf, sizeof(buf), "%F %T %z", &tm); + std::cout << "[" << buf << "]"; + } - switch (d_format) - { - case 0: - d_fos << s << std::endl; - break; - case 1: - su = (uint8_t *) pmt::blob_data (msg); - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - d_fos << "0x" << std::hex << std::setw (2) << std::setfill ('0') + switch (d_format) { + case 0: // binary + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + std::cout << s[i]; + } + std::cout << std::endl; + break; + case 1: // hex annotated + su = (uint8_t *) pmt::blob_data(msg); + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (uint32_t) su[i] << " "; - } - d_fos << std::endl; - break; - case 2: - su = (uint8_t *) pmt::blob_data (msg); - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - d_fos << "0b" << std::bitset<8> (su[i]) << " "; - } - d_fos << std::endl; - break; - default: - throw std::invalid_argument("Invalid format"); - } } - - void - multi_format_msg_sink_impl::msg_handler_stdout (pmt::pmt_t msg) - { - uint8_t *su; - char buf[256]; - std::string s ((const char *) pmt::blob_data (msg), - pmt::blob_length (msg)); - - if(d_timestamp) { - std::time_t t = std::time(nullptr); - std::tm tm = *std::localtime(&t); - strftime(buf, sizeof(buf), "%F %T %z", &tm); - std::cout << "[" << buf << "]"; - } - - switch (d_format) - { - case 0: // binary - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - std::cout << s[i]; - } - std::cout << std::endl; - break; - case 1: // hex annotated - su = (uint8_t *) pmt::blob_data (msg); - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - std::cout << "0x" << std::hex << std::setw (2) << std::setfill ('0') - << (uint32_t) su[i] << " "; - } - std::cout << std::endl; - break; - case 2: // binary annotated - su = (uint8_t *) pmt::blob_data (msg); - for (size_t i = 0; i < pmt::blob_length (msg); i++) { - std::cout << "0b" << std::bitset<8> (su[i]) << " "; - } - std::cout << std::endl; - break; - default: - throw std::invalid_argument("Invalid format"); - } + std::cout << std::endl; + break; + case 2: // binary annotated + su = (uint8_t *) pmt::blob_data(msg); + for (size_t i = 0; i < pmt::blob_length(msg); i++) { + std::cout << "0b" << std::bitset<8> (su[i]) << " "; } + std::cout << std::endl; + break; + default: + throw std::invalid_argument("Invalid format"); + } +} - /* - * The private constructor - */ - multi_format_msg_sink_impl::multi_format_msg_sink_impl ( - size_t format, bool timestamp, bool out_stdout, - const std::string& filepath) : - gr::block ("multi_format_msg_sink", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_format (format), - d_timestamp (timestamp), - d_stdout (out_stdout) - { - message_port_register_in (pmt::mp ("in")); - if(out_stdout) { - set_msg_handler ( - pmt::mp ("in"), - boost::bind (&multi_format_msg_sink_impl::msg_handler_stdout, - this, _1)); - } - else{ - d_fos.open(filepath); - set_msg_handler ( - pmt::mp ("in"), - boost::bind (&multi_format_msg_sink_impl::msg_handler_file, - this, _1)); - } - } +/* + * The private constructor + */ +multi_format_msg_sink_impl::multi_format_msg_sink_impl( + size_t format, bool timestamp, bool out_stdout, + const std::string &filepath) : + gr::block("multi_format_msg_sink", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_format(format), + d_timestamp(timestamp), + d_stdout(out_stdout) +{ + message_port_register_in(pmt::mp("in")); + if (out_stdout) { + set_msg_handler( + pmt::mp("in"), + boost::bind(&multi_format_msg_sink_impl::msg_handler_stdout, + this, _1)); + } + else { + d_fos.open(filepath); + set_msg_handler( + pmt::mp("in"), + boost::bind(&multi_format_msg_sink_impl::msg_handler_file, + this, _1)); + } +} - multi_format_msg_sink_impl::~multi_format_msg_sink_impl () - { - if(!d_stdout) { - d_fos.close(); - } - } +multi_format_msg_sink_impl::~multi_format_msg_sink_impl() +{ + if (!d_stdout) { + d_fos.close(); + } +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/multi_format_msg_sink_impl.h b/lib/multi_format_msg_sink_impl.h index 2061acb..b910943 100644 --- a/lib/multi_format_msg_sink_impl.h +++ b/lib/multi_format_msg_sink_impl.h @@ -24,33 +24,30 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class multi_format_msg_sink_impl : public multi_format_msg_sink - { - private: - void - msg_handler_stdout (pmt::pmt_t msg); - void - msg_handler_file (pmt::pmt_t msg); +class multi_format_msg_sink_impl : public multi_format_msg_sink { +private: + void + msg_handler_stdout(pmt::pmt_t msg); + void + msg_handler_file(pmt::pmt_t msg); - const size_t d_format; - const bool d_timestamp; - const bool d_stdout; - std::ofstream d_fos; + const size_t d_format; + const bool d_timestamp; + const bool d_stdout; + std::ofstream d_fos; - public: - multi_format_msg_sink_impl (size_t format, bool timestamp, - bool out_stdout, const std::string& filepath); +public: + multi_format_msg_sink_impl(size_t format, bool timestamp, + bool out_stdout, const std::string &filepath); - ~multi_format_msg_sink_impl (); + ~multi_format_msg_sink_impl(); - }; +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_multi_format_MSG_SINK_IMPL_H */ diff --git a/lib/noaa_apt_sink_impl.cc b/lib/noaa_apt_sink_impl.cc index a86a483..c351b4f 100644 --- a/lib/noaa_apt_sink_impl.cc +++ b/lib/noaa_apt_sink_impl.cc @@ -27,267 +27,272 @@ #include -namespace gr +namespace gr { +namespace satnogs { +// Noaa apt sync pattern A +// (see https://sourceforge.isae.fr/attachments/download/1813/apt_synch.gif) +const bool noaa_apt_sink_impl::synca_seq[] = {false, false, false, false, + true, true, false, false, // Pulse 1 + true, true, false, false, // Pulse 2 + true, true, false, false, // Pulse 3 + true, true, false, false, // Pulse 4 + true, true, false, false, // Pulse 5 + true, true, false, false, // Pulse 6 + true, true, false, false, // Pulse 7 + false, false, false, false, + false, false, false, false + }; + +// Noaa apt sync pattern B +// (see https://sourceforge.isae.fr/attachments/download/1813/apt_synch.gif) +const bool noaa_apt_sink_impl::syncb_seq[] = {false, false, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + false + }; + + + +noaa_apt_sink::sptr +noaa_apt_sink::make(const char *filename_png, size_t width, size_t height, + bool sync, bool flip) { - namespace satnogs - { - // Noaa apt sync pattern A - // (see https://sourceforge.isae.fr/attachments/download/1813/apt_synch.gif) - const bool noaa_apt_sink_impl::synca_seq[] = {false, false, false, false, - true, true, false, false, // Pulse 1 - true, true, false, false, // Pulse 2 - true, true, false, false, // Pulse 3 - true, true, false, false, // Pulse 4 - true, true, false, false, // Pulse 5 - true, true, false, false, // Pulse 6 - true, true, false, false, // Pulse 7 - false, false, false, false, - false, false, false, false}; - - // Noaa apt sync pattern B - // (see https://sourceforge.isae.fr/attachments/download/1813/apt_synch.gif) - const bool noaa_apt_sink_impl::syncb_seq[] = {false, false, false, false, - true, true, true, false, false, - true, true, true, false, false, - true, true, true, false, false, - true, true, true, false, false, - true, true, true, false, false, - true, true, true, false, false, - true, true, true, false, false, - false}; - - - - noaa_apt_sink::sptr - noaa_apt_sink::make (const char *filename_png, size_t width, size_t height, - bool sync, bool flip) - { - return gnuradio::get_initial_sptr ( - new noaa_apt_sink_impl (filename_png, width, height, sync, + return gnuradio::get_initial_sptr( + new noaa_apt_sink_impl(filename_png, width, height, sync, flip)); +} + + +/* + * The private constructor + */ +noaa_apt_sink_impl::noaa_apt_sink_impl(const char *filename_png, + size_t width, size_t height, + bool sync, bool flip) : + gr::sync_block("noaa_apt_sink", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(0, 0, 0)), + f_average_alpha(0.25), + d_filename_png(filename_png), + d_width(width), + d_height(height), + d_synchronize_opt(sync), + d_flip(flip), + d_history_length(40), + d_has_sync(false), + d_image_received(false), + d_current_x(0), + d_current_y(0), + d_num_images(0), + f_max_level(0.0), + f_min_level(1.0), + f_average(0.0) +{ + set_history(d_history_length); + d_full_image = png::image(d_width, d_height); +} + +void +noaa_apt_sink_impl::write_image(png::image image, + std::string filename) +{ + // In case the flip option is set + if (d_flip) { + size_t width = image.get_width(); + size_t height = image.get_height(); + + // An image of same size is created ... + png::image flipped(width, height); + + // ... and all the lines are copied over reverse order + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + png::gray_pixel pixel = image.get_pixel(x, height - y - 1); + flipped.set_pixel(x, y, pixel); + } + } + // Write out the flipped image + flipped.write(filename); + } + // In case the flip option is not set + else { + // Write out the original + image.write(filename); + } +} + +noaa_apt_sink_impl::~noaa_apt_sink_impl() +{ + +} +bool +noaa_apt_sink_impl::stop() +{ + if (!d_image_received) { + write_image(d_full_image, d_filename_png); + } + return true; +} + +void noaa_apt_sink_impl::set_pixel(size_t x, size_t y, float sample) +{ + // We can encounter NaN here since skip_to read the history whithout checking + if (std::isnan(sample)) { + sample = 0.0; + } + + // Adjust dynamic range, using minimum and maximum values + sample = (sample - f_min_level) / (f_max_level - f_min_level) * 255; + // Set the pixel in the full image + d_full_image.set_pixel(x, y, sample); +} + +void +noaa_apt_sink_impl::skip_to(size_t new_x, size_t pos, const float *samples) +{ + // Check if the skip is forward or backward + if (new_x > d_current_x) { + // In case it is forward there will be a new_x - d_current_x sized hole + // in the image. Holes up 39 pixels can be filled from the modules history + size_t dist = std::min(size_t(39), new_x - d_current_x); + // Fill the hole using the previous samples of pos + for (size_t i = 0; i < dist; i++) { + set_pixel(new_x - dist + i, d_current_y, samples[pos - dist + i]); + } + } + // Jump to new location + d_current_x = new_x; +} + + +noaa_apt_sync_marker +noaa_apt_sink_impl::is_marker(size_t pos, const float *samples) +{ + // Initialize counters for 'hacky' correlation + size_t count_a = 0; + size_t count_b = 0; + + for (size_t i = 0; i < 40; i++) { + // history of previous 39 samples + current one + // -> start 39 samples in the past + float sample = samples[pos - 39 + i]; + // Remove DC-offset (aka. the average value of the sync pattern) + sample = sample - f_average; + + // Very basic 1/0 correlation between pattern constan and history + if ((sample > 0 && synca_seq[i]) || (sample < 0 && !synca_seq[i])) { + count_a += 1; + } + if ((sample > 0 && syncb_seq[i]) || (sample < 0 && !syncb_seq[i])) { + count_b += 1; + } + } + + // Prefer sync pattern a as it is detected more reliable + if (count_a > 35) { + return noaa_apt_sync_marker::SYNC_A; + } + else if (count_b > 35) { + return noaa_apt_sync_marker::SYNC_B; + } + else { + return noaa_apt_sync_marker::NONE; + } +} + + +int +noaa_apt_sink_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + /* If we have already produced one image, ignore the remaining observation*/ + if (d_image_received) { + return noutput_items; + } + + // Structure of in[]: + // - d_history_length many historical samples + // - noutput_items many samples to process + for (size_t i = d_history_length - 1; + i < noutput_items + d_history_length - 1; i++) { + + // Get the current sample + float sample = in[i]; + + // For some reason the first sample on a Raspberry Pi can be NaN + if (std::isnan(sample)) { + continue; } + // Update min and max level to adjust dynamic range in set pixel + f_max_level = std::fmax(f_max_level, sample); + f_min_level = std::fmin(f_min_level, sample); - /* - * The private constructor - */ - noaa_apt_sink_impl::noaa_apt_sink_impl (const char *filename_png, - size_t width, size_t height, - bool sync, bool flip) : - gr::sync_block ("noaa_apt_sink", - gr::io_signature::make (1, 1, sizeof(float)), - gr::io_signature::make (0, 0, 0)), - f_average_alpha (0.25), - d_filename_png (filename_png), - d_width (width), - d_height (height), - d_synchronize_opt (sync), - d_flip (flip), - d_history_length (40), - d_has_sync (false), - d_image_received(false), - d_current_x (0), - d_current_y (0), - d_num_images (0), - f_max_level(0.0), - f_min_level(1.0), - f_average(0.0) - { - set_history(d_history_length); - d_full_image = png::image(d_width, d_height); + // Update exponential smoothing average used in sync pattern detection + f_average = f_average_alpha * sample + (1.0 - f_average_alpha) * f_average; + + // If line sync is enabled + if (d_synchronize_opt) { + // Check if the history for the current sample is a sync pattern + noaa_apt_sync_marker marker = is_marker(i, in); + + // For pattern a + if (marker == noaa_apt_sync_marker::SYNC_A) { + // Skip to right location, pattern starts 40 samples in the past + skip_to(39, i, in); + // If this is the first sync, reset min and max + if (!d_has_sync) { + f_max_level = 0.0; + f_min_level = 1.0; + d_has_sync = true; + } + } + // For pattern b + else if (marker == noaa_apt_sync_marker::SYNC_B) { + // Skip to right location, pattern starts 40 samples in the past + skip_to(d_width / 2 + 39, i, in); + // If this is the first sync, reset min and max + if (!d_has_sync) { + f_max_level = 0.0; + f_min_level = 1.0; + d_has_sync = true; + } + } } - void - noaa_apt_sink_impl::write_image (png::image image, - std::string filename) - { - // In case the flip option is set - if(d_flip) { - size_t width = image.get_width(); - size_t height = image.get_height(); + // Set the the pixel at the current position + set_pixel(d_current_x, d_current_y, sample); - // An image of same size is created ... - png::image flipped(width, height); + // Increment x position + d_current_x += 1; + // If we are beyond the end of line + if (d_current_x >= d_width) { + // Increment y position + d_current_y += 1; + // Reset x position to line start + d_current_x = 0; - // ... and all the lines are copied over reverse order - for(size_t y = 0; y < height; y++) { - for(size_t x = 0; x < width; x++) { - png::gray_pixel pixel = image.get_pixel(x, height - y - 1); - flipped.set_pixel(x, y, pixel); - } - } - // Write out the flipped image - flipped.write(filename); - } - // In case the flip option is not set - else { - // Write out the original - image.write(filename); - } + // Split the image if there are enough lines decoded + if (d_current_y >= d_height) { + d_current_y = 0; + d_num_images += 1; + // Write out the full image + write_image(d_full_image, d_filename_png); + d_image_received = true; + } } + } - noaa_apt_sink_impl::~noaa_apt_sink_impl () { + // Tell gnu radio how many samples were consumed + return noutput_items; +} - } - bool - noaa_apt_sink_impl::stop(){ - if(!d_image_received){ - write_image(d_full_image, d_filename_png); - } - return true; - } - - void noaa_apt_sink_impl::set_pixel (size_t x, size_t y, float sample) { - // We can encounter NaN here since skip_to read the history whithout checking - if(std::isnan(sample)) { - sample = 0.0; - } - - // Adjust dynamic range, using minimum and maximum values - sample = (sample - f_min_level) / (f_max_level - f_min_level) * 255; - // Set the pixel in the full image - d_full_image.set_pixel(x, y, sample); - } - - void - noaa_apt_sink_impl::skip_to (size_t new_x, size_t pos, const float *samples) { - // Check if the skip is forward or backward - if(new_x > d_current_x) { - // In case it is forward there will be a new_x - d_current_x sized hole - // in the image. Holes up 39 pixels can be filled from the modules history - size_t dist = std::min(size_t(39), new_x - d_current_x); - // Fill the hole using the previous samples of pos - for(size_t i = 0; i < dist; i++) { - set_pixel(new_x - dist + i, d_current_y, samples[pos - dist + i]); - } - } - // Jump to new location - d_current_x = new_x; - } - - - noaa_apt_sync_marker - noaa_apt_sink_impl::is_marker(size_t pos, const float *samples) { - // Initialize counters for 'hacky' correlation - size_t count_a = 0; - size_t count_b = 0; - - for(size_t i = 0; i < 40; i++) { - // history of previous 39 samples + current one - // -> start 39 samples in the past - float sample = samples[pos - 39 + i]; - // Remove DC-offset (aka. the average value of the sync pattern) - sample = sample - f_average; - - // Very basic 1/0 correlation between pattern constan and history - if((sample > 0 && synca_seq[i]) || (sample < 0 && !synca_seq[i])) { - count_a += 1; - } - if((sample > 0 && syncb_seq[i]) || (sample < 0 && !syncb_seq[i])) { - count_b += 1; - } - } - - // Prefer sync pattern a as it is detected more reliable - if(count_a > 35) { - return noaa_apt_sync_marker::SYNC_A; - } - else if(count_b > 35) { - return noaa_apt_sync_marker::SYNC_B; - } - else { - return noaa_apt_sync_marker::NONE; - } - } - - - int - noaa_apt_sink_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const float *in = (const float *) input_items[0]; - /* If we have already produced one image, ignore the remaining observation*/ - if(d_image_received){ - return noutput_items; - } - - // Structure of in[]: - // - d_history_length many historical samples - // - noutput_items many samples to process - for (size_t i = d_history_length - 1; - i < noutput_items + d_history_length - 1; i++) { - - // Get the current sample - float sample = in[i]; - - // For some reason the first sample on a Raspberry Pi can be NaN - if(std::isnan(sample)) { - continue; - } - - // Update min and max level to adjust dynamic range in set pixel - f_max_level = std::fmax(f_max_level, sample); - f_min_level = std::fmin(f_min_level, sample); - - // Update exponential smoothing average used in sync pattern detection - f_average = f_average_alpha * sample + (1.0 - f_average_alpha) * f_average; - - // If line sync is enabled - if(d_synchronize_opt) { - // Check if the history for the current sample is a sync pattern - noaa_apt_sync_marker marker = is_marker(i, in); - - // For pattern a - if(marker == noaa_apt_sync_marker::SYNC_A) { - // Skip to right location, pattern starts 40 samples in the past - skip_to(39, i, in); - // If this is the first sync, reset min and max - if(!d_has_sync) { - f_max_level = 0.0; - f_min_level = 1.0; - d_has_sync = true; - } - } - // For pattern b - else if(marker == noaa_apt_sync_marker::SYNC_B) { - // Skip to right location, pattern starts 40 samples in the past - skip_to(d_width / 2 + 39, i, in); - // If this is the first sync, reset min and max - if(!d_has_sync) { - f_max_level = 0.0; - f_min_level = 1.0; - d_has_sync = true; - } - } - } - - // Set the the pixel at the current position - set_pixel(d_current_x, d_current_y, sample); - - // Increment x position - d_current_x += 1; - // If we are beyond the end of line - if(d_current_x >= d_width) { - // Increment y position - d_current_y += 1; - // Reset x position to line start - d_current_x = 0; - - // Split the image if there are enough lines decoded - if(d_current_y >= d_height) { - d_current_y = 0; - d_num_images += 1; - // Write out the full image - write_image(d_full_image, d_filename_png); - d_image_received = true; - } - } - } - - // Tell gnu radio how many samples were consumed - return noutput_items; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/noaa_apt_sink_impl.h b/lib/noaa_apt_sink_impl.h index aa620fe..d627a78 100644 --- a/lib/noaa_apt_sink_impl.h +++ b/lib/noaa_apt_sink_impl.h @@ -28,83 +28,80 @@ -namespace gr -{ - namespace satnogs - { - enum class noaa_apt_sync_marker {SYNC_A, SYNC_B, NONE}; +namespace gr { +namespace satnogs { +enum class noaa_apt_sync_marker {SYNC_A, SYNC_B, NONE}; - class noaa_apt_sink_impl : public noaa_apt_sink - { - private: - // Factor exponential smoothing average, - // which is used for sync pattern detection - const float f_average_alpha; - static const bool synca_seq[]; - static const bool syncb_seq[]; +class noaa_apt_sink_impl : public noaa_apt_sink { +private: + // Factor exponential smoothing average, + // which is used for sync pattern detection + const float f_average_alpha; + static const bool synca_seq[]; + static const bool syncb_seq[]; - std::string d_filename_png; - size_t d_width; - size_t d_height; - bool d_synchronize_opt; - bool d_flip; - size_t d_history_length; - bool d_has_sync; - bool d_image_received; + std::string d_filename_png; + size_t d_width; + size_t d_height; + bool d_synchronize_opt; + bool d_flip; + size_t d_history_length; + bool d_has_sync; + bool d_image_received; - png::image d_full_image; - png::image d_left_image; - png::image d_right_image; - std::string d_full_filename; - std::string d_left_filename; - std::string d_right_filename; + png::image d_full_image; + png::image d_left_image; + png::image d_right_image; + std::string d_full_filename; + std::string d_left_filename; + std::string d_right_filename; - size_t d_current_x; - size_t d_current_y; - size_t d_num_images; + size_t d_current_x; + size_t d_current_y; + size_t d_num_images; - float f_max_level; - float f_min_level; - float f_average; + float f_max_level; + float f_min_level; + float f_average; - public: - noaa_apt_sink_impl (const char *filename_png, size_t width, size_t height, - bool sync, bool flip); - ~noaa_apt_sink_impl (); +public: + noaa_apt_sink_impl(const char *filename_png, size_t width, size_t height, + bool sync, bool flip); + ~noaa_apt_sink_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); - bool - stop(); - private: + bool + stop(); +private: - /* - * Checks if the history portion of the input contains a sync marker. - * Matches the 40 samples before pos against the patterns. - */ - noaa_apt_sync_marker - is_marker (size_t pos, const float *samples); + /* + * Checks if the history portion of the input contains a sync marker. + * Matches the 40 samples before pos against the patterns. + */ + noaa_apt_sync_marker + is_marker(size_t pos, const float *samples); - // Sets the pixel indicated by coordinates in the images (both full and split) - void - set_pixel (size_t x, size_t y, float sample); + // Sets the pixel indicated by coordinates in the images (both full and split) + void + set_pixel(size_t x, size_t y, float sample); - /* - * Updates d_current_x to new_x, - * while using historical samples to fill any resulting gaps in the images. - */ - void - skip_to (size_t new_x, size_t pos, const float *samples); + /* + * Updates d_current_x to new_x, + * while using historical samples to fill any resulting gaps in the images. + */ + void + skip_to(size_t new_x, size_t pos, const float *samples); - // Writes a single image to disk, also takes care of flipping - void - write_image (png::image image, std::string filename); - }; + // Writes a single image to disk, also takes care of flipping + void + write_image(png::image image, std::string filename); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_NOAA_APT_SINK_IMPL_H */ diff --git a/lib/ogg_encoder_impl.cc b/lib/ogg_encoder_impl.cc index b07f232..50971de 100644 --- a/lib/ogg_encoder_impl.cc +++ b/lib/ogg_encoder_impl.cc @@ -31,107 +31,109 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +ogg_encoder::sptr +ogg_encoder::make(char *filename, double samp_rate, float quality) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new ogg_encoder_impl(filename, samp_rate, quality)); +} - ogg_encoder::sptr - ogg_encoder::make (char* filename, double samp_rate, float quality) - { - return gnuradio::get_initial_sptr ( - new ogg_encoder_impl (filename, samp_rate, quality)); +/* + * The private constructor + */ +ogg_encoder_impl::ogg_encoder_impl(char *filename, double samp_rate, + float quality) : + gr::sync_block("ogg_encoder", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(0, 0, 0)) +{ + d_quality = quality; + d_out = fopen(filename, "wb"); + d_samp_rate = samp_rate; + vorbis_info_init(&d_vi); + int ret = vorbis_encode_init_vbr(&d_vi, 1, d_samp_rate, d_quality); + if (ret) { + exit(1); + } + + vorbis_comment_init(&d_vc); + vorbis_comment_add_tag(&d_vc, "ENCODER", "satnogs ogg encoder"); + + vorbis_analysis_init(&d_vd, &d_vi); + vorbis_block_init(&d_vd, &d_vb); + + srand(time(NULL)); + ogg_stream_init(&d_os, rand()); + + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&d_vd, &d_vc, &header, &header_comm, + &header_code); + ogg_stream_packetin(&d_os, &header); + ogg_stream_packetin(&d_os, &header_comm); + ogg_stream_packetin(&d_os, &header_code); + int result = 1; + while (result) { + result = ogg_stream_flush(&d_os, &d_og); + if (result == 0) { + break; } + fwrite(d_og.header, 1, d_og.header_len, d_out); + fwrite(d_og.body, 1, d_og.body_len, d_out); + } +} - /* - * The private constructor - */ - ogg_encoder_impl::ogg_encoder_impl (char* filename, double samp_rate, - float quality) : - gr::sync_block ("ogg_encoder", - gr::io_signature::make (1, 1, sizeof(float)), - gr::io_signature::make (0, 0, 0)) - { - d_quality = quality; - d_out = fopen (filename, "wb"); - d_samp_rate = samp_rate; - vorbis_info_init (&d_vi); - int ret = vorbis_encode_init_vbr (&d_vi, 1, d_samp_rate, d_quality); - if (ret) - exit (1); +ogg_encoder_impl::~ogg_encoder_impl() +{ + vorbis_analysis_wrote(&d_vd, 0); + ogg_stream_clear(&d_os); + vorbis_block_clear(&d_vb); + vorbis_dsp_clear(&d_vd); + vorbis_comment_clear(&d_vc); + vorbis_info_clear(&d_vi); + fclose(d_out); +} - vorbis_comment_init (&d_vc); - vorbis_comment_add_tag (&d_vc, "ENCODER", "satnogs ogg encoder"); +int +ogg_encoder_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + int i; + float **buffer = vorbis_analysis_buffer(&d_vd, noutput_items); + memcpy(buffer[0], in, noutput_items * sizeof(float)); - vorbis_analysis_init (&d_vd, &d_vi); - vorbis_block_init (&d_vd, &d_vb); + vorbis_analysis_wrote(&d_vd, noutput_items); - srand (time (NULL)); - ogg_stream_init (&d_os, rand ()); + while (vorbis_analysis_blockout(&d_vd, &d_vb) == 1) { + vorbis_analysis(&d_vb, NULL); + vorbis_bitrate_addblock(&d_vb); - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; + while (vorbis_bitrate_flushpacket(&d_vd, &d_op)) { - vorbis_analysis_headerout (&d_vd, &d_vc, &header, &header_comm, - &header_code); - ogg_stream_packetin (&d_os, &header); - ogg_stream_packetin (&d_os, &header_comm); - ogg_stream_packetin (&d_os, &header_code); + ogg_stream_packetin(&d_os, &d_op); int result = 1; while (result) { - result = ogg_stream_flush (&d_os, &d_og); - if (result == 0) + int result = ogg_stream_pageout(&d_os, &d_og); + if (result == 0) { break; - fwrite (d_og.header, 1, d_og.header_len, d_out); - fwrite (d_og.body, 1, d_og.body_len, d_out); - } - } - - ogg_encoder_impl::~ogg_encoder_impl () - { - vorbis_analysis_wrote (&d_vd, 0); - ogg_stream_clear (&d_os); - vorbis_block_clear (&d_vb); - vorbis_dsp_clear (&d_vd); - vorbis_comment_clear (&d_vc); - vorbis_info_clear (&d_vi); - fclose (d_out); - } - - int - ogg_encoder_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const char *in = (const char *) input_items[0]; - int i; - float **buffer = vorbis_analysis_buffer (&d_vd, noutput_items); - memcpy(buffer[0], in, noutput_items * sizeof(float)); - - vorbis_analysis_wrote (&d_vd, noutput_items); - - while (vorbis_analysis_blockout (&d_vd, &d_vb) == 1) { - vorbis_analysis (&d_vb, NULL); - vorbis_bitrate_addblock (&d_vb); - - while (vorbis_bitrate_flushpacket (&d_vd, &d_op)) { - - ogg_stream_packetin (&d_os, &d_op); - int result = 1; - while (result) { - int result = ogg_stream_pageout (&d_os, &d_og); - if (result == 0) - break; - fwrite (d_og.header, 1, d_og.header_len, d_out); - fwrite (d_og.body, 1, d_og.body_len, d_out); - if (ogg_page_eos (&d_og)) - result = 1; - } + } + fwrite(d_og.header, 1, d_og.header_len, d_out); + fwrite(d_og.body, 1, d_og.body_len, d_out); + if (ogg_page_eos(&d_og)) { + result = 1; } } - return noutput_items; } + } + return noutput_items; +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/ogg_encoder_impl.h b/lib/ogg_encoder_impl.h index c8cf28b..7615a98 100644 --- a/lib/ogg_encoder_impl.h +++ b/lib/ogg_encoder_impl.h @@ -24,39 +24,36 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class ogg_encoder_impl : public ogg_encoder - { - private: - // Nothing to declare in this block. - ogg_stream_state d_os; - ogg_page d_og; - ogg_packet d_op; +class ogg_encoder_impl : public ogg_encoder { +private: + // Nothing to declare in this block. + ogg_stream_state d_os; + ogg_page d_og; + ogg_packet d_op; - vorbis_info d_vi; - vorbis_comment d_vc; + vorbis_info d_vi; + vorbis_comment d_vc; - vorbis_dsp_state d_vd; - vorbis_block d_vb; - FILE* d_out; - double d_samp_rate; - float d_quality; + vorbis_dsp_state d_vd; + vorbis_block d_vb; + FILE *d_out; + double d_samp_rate; + float d_quality; - public: - ogg_encoder_impl (char* filename, double samp_rate, float quality); - ~ogg_encoder_impl (); +public: + ogg_encoder_impl(char *filename, double samp_rate, float quality); + ~ogg_encoder_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_OGG_ENCODER_IMPL_H */ diff --git a/lib/ogg_source_impl.cc b/lib/ogg_source_impl.cc index 8b46eb1..0b333d8 100644 --- a/lib/ogg_source_impl.cc +++ b/lib/ogg_source_impl.cc @@ -33,111 +33,111 @@ #define PCM_BUF_SIZE 4096 namespace gr { - namespace satnogs { +namespace satnogs { - ogg_source::sptr - ogg_source::make (const std::string& filename, int channels, bool repeat) - { - return gnuradio::get_initial_sptr ( - new ogg_source_impl (filename, channels, repeat)); - } +ogg_source::sptr +ogg_source::make(const std::string &filename, int channels, bool repeat) +{ + return gnuradio::get_initial_sptr( + new ogg_source_impl(filename, channels, repeat)); +} +/* + * The private constructor + */ +ogg_source_impl::ogg_source_impl(const std::string &filename, + int channels, bool repeat) : + gr::sync_block( + "ogg_source", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(channels, channels, sizeof(float))), + d_channels(channels), + d_repeat(repeat) +{ + if (channels < 1) { + throw std::invalid_argument("At least one output channels should" + " be specified"); + } + + if (ov_fopen(filename.c_str(), &d_ogvorb_f) < 0) { + throw std::invalid_argument("Invalid .ogg file"); + } + + vorbis_info *vi = ov_info(&d_ogvorb_f, -1); + if (vi->channels != (int) channels) { + throw std::invalid_argument( + std::string("Channels number specified (") + + std::to_string(channels) + + ") does not match the channels of " + "the ogg stream (" + std::to_string(vi->channels) + ")"); + } + + const int alignment_multiple = volk_get_alignment() / sizeof(float); + set_alignment(std::max(1, alignment_multiple)); + set_max_noutput_items(PCM_BUF_SIZE); + + d_in_buffer = (int16_t *) volk_malloc(PCM_BUF_SIZE * sizeof(int16_t), + volk_get_alignment()); + d_out_buffer = (float *) volk_malloc(PCM_BUF_SIZE * sizeof(float), + volk_get_alignment()); + if (!d_in_buffer || !d_out_buffer) { + throw std::runtime_error("Could not allocate memory"); + } +} + +/* + * Our virtual destructor. + */ +ogg_source_impl::~ogg_source_impl() +{ + ov_clear(&d_ogvorb_f); + volk_free(d_in_buffer); + volk_free(d_out_buffer); +} + +int +ogg_source_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + long int ret; + int section = 0; + int available = (noutput_items / d_channels); + int available_samples = 0; + int produced = 0; + + ret = ov_read(&d_ogvorb_f, (char *)d_in_buffer, + available * sizeof(int16_t), + 0, sizeof(int16_t), 1, §ion); + if (ret <= 0) { /* - * The private constructor + * If return value is EOF and the repeat mode is set seek back to the + * start of the ogg stream */ - ogg_source_impl::ogg_source_impl (const std::string& filename, - int channels, bool repeat) : - gr::sync_block ( - "ogg_source", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (channels, channels, sizeof(float))), - d_channels (channels), - d_repeat (repeat) - { - if (channels < 1) { - throw std::invalid_argument ("At least one output channels should" - " be specified"); - } - - if (ov_fopen (filename.c_str (), &d_ogvorb_f) < 0) { - throw std::invalid_argument ("Invalid .ogg file"); - } - - vorbis_info *vi = ov_info (&d_ogvorb_f, -1); - if (vi->channels != (int) channels) { - throw std::invalid_argument ( - std::string ("Channels number specified (") - + std::to_string (channels) - + ") does not match the channels of " - "the ogg stream (" + std::to_string (vi->channels) + ")"); - } - - const int alignment_multiple = volk_get_alignment () / sizeof(float); - set_alignment (std::max (1, alignment_multiple)); - set_max_noutput_items (PCM_BUF_SIZE); - - d_in_buffer = (int16_t *) volk_malloc (PCM_BUF_SIZE * sizeof(int16_t), - volk_get_alignment ()); - d_out_buffer = (float *) volk_malloc (PCM_BUF_SIZE * sizeof(float), - volk_get_alignment ()); - if(!d_in_buffer || !d_out_buffer) { - throw std::runtime_error("Could not allocate memory"); + if (ret == 0 && d_repeat) { + if (ov_seekable(&d_ogvorb_f)) { + ov_time_seek(&d_ogvorb_f, 0); + return 0; } + LOG_WARN("File is not seakable."); } + return WORK_DONE; + } - /* - * Our virtual destructor. - */ - ogg_source_impl::~ogg_source_impl() - { - ov_clear(&d_ogvorb_f); - volk_free(d_in_buffer); - volk_free(d_out_buffer); + available_samples = ret / sizeof(int16_t); + /* Convert to float the signed-short audio samples */ + volk_16i_s32f_convert_32f(d_out_buffer, d_in_buffer, 2 << 15, + available_samples); + + /* De-interleave the available channels */ + for (int i = 0; i < available_samples; i += d_channels, produced++) { + for (int chan = 0; chan < d_channels; chan++) { + ((float *)output_items[chan])[produced] = d_out_buffer[i * d_channels + chan]; } + } - int - ogg_source_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - long int ret; - int section = 0; - int available = (noutput_items / d_channels); - int available_samples = 0; - int produced = 0; + return produced; +} - ret = ov_read (&d_ogvorb_f, (char *)d_in_buffer, - available * sizeof(int16_t), - 0, sizeof(int16_t), 1, §ion); - if(ret <= 0) { - /* - * If return value is EOF and the repeat mode is set seek back to the - * start of the ogg stream - */ - if(ret == 0 && d_repeat) { - if(ov_seekable(&d_ogvorb_f)){ - ov_time_seek(&d_ogvorb_f, 0); - return 0; - } - LOG_WARN("File is not seakable."); - } - return WORK_DONE; - } - - available_samples = ret / sizeof(int16_t); - /* Convert to float the signed-short audio samples */ - volk_16i_s32f_convert_32f (d_out_buffer, d_in_buffer, 2 << 15, - available_samples); - - /* De-interleave the available channels */ - for(int i = 0; i < available_samples; i += d_channels, produced++) { - for(int chan = 0; chan < d_channels; chan++){ - ((float *)output_items[chan])[produced] = d_out_buffer[i * d_channels + chan]; - } - } - - return produced; - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/ogg_source_impl.h b/lib/ogg_source_impl.h index 36d4ff3..4c4e398 100644 --- a/lib/ogg_source_impl.h +++ b/lib/ogg_source_impl.h @@ -25,33 +25,30 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class ogg_source_impl : public ogg_source - { - private: - const int d_channels; - const bool d_repeat; - OggVorbis_File d_ogvorb_f; +class ogg_source_impl : public ogg_source { +private: + const int d_channels; + const bool d_repeat; + OggVorbis_File d_ogvorb_f; - int16_t *d_in_buffer; - float *d_out_buffer; + int16_t *d_in_buffer; + float *d_out_buffer; - public: - ogg_source_impl (const std::string& filename, int channels, - bool repeat); - ~ogg_source_impl (); +public: + ogg_source_impl(const std::string &filename, int channels, + bool repeat); + ~ogg_source_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_OGG_SOURCE_IMPL_H */ diff --git a/lib/qa_ax25_decoder.cc b/lib/qa_ax25_decoder.cc index aa451e2..fc9d3fb 100644 --- a/lib/qa_ax25_decoder.cc +++ b/lib/qa_ax25_decoder.cc @@ -23,13 +23,11 @@ #include "qa_ax25_decoder.h" #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { void -qa_ax25_decoder::t1 () +qa_ax25_decoder::t1() { // Put test here } diff --git a/lib/qa_ax25_decoder.h b/lib/qa_ax25_decoder.h index 0ec5e14..8b525b0 100644 --- a/lib/qa_ax25_decoder.h +++ b/lib/qa_ax25_decoder.h @@ -25,20 +25,19 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - class qa_ax25_decoder : public CppUnit::TestCase - { - public: - CPPUNIT_TEST_SUITE(qa_ax25_decoder); - CPPUNIT_TEST(t1); - CPPUNIT_TEST_SUITE_END(); +class qa_ax25_decoder : public CppUnit::TestCase { +public: + CPPUNIT_TEST_SUITE(qa_ax25_decoder); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END(); - private: - void t1(); - }; +private: + void t1(); +}; - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ #endif /* _QA_AX25_DECODER_H_ */ diff --git a/lib/qa_crc.cc b/lib/qa_crc.cc index 7ecc225..f3b25dc 100644 --- a/lib/qa_crc.cc +++ b/lib/qa_crc.cc @@ -23,13 +23,11 @@ #include "qa_crc.h" #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { void -qa_crc::t1 () +qa_crc::t1() { // Put test here } diff --git a/lib/qa_crc.h b/lib/qa_crc.h index a0c7323..2e916b9 100644 --- a/lib/qa_crc.h +++ b/lib/qa_crc.h @@ -25,20 +25,19 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - class qa_crc : public CppUnit::TestCase - { - public: - CPPUNIT_TEST_SUITE(qa_crc); - CPPUNIT_TEST(t1); - CPPUNIT_TEST_SUITE_END(); +class qa_crc : public CppUnit::TestCase { +public: + CPPUNIT_TEST_SUITE(qa_crc); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END(); - private: - void t1(); - }; +private: + void t1(); +}; - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ #endif /* _QA_CRC_H_ */ diff --git a/lib/qa_golay24.cc b/lib/qa_golay24.cc index f83ece9..ed2e94c 100644 --- a/lib/qa_golay24.cc +++ b/lib/qa_golay24.cc @@ -36,7 +36,7 @@ qa_golay24::example_47() golay24 gol; uint32_t r = 0b100000110100110000000001; uint32_t res; - bool ret = gol.decode24 (&res, r); + bool ret = gol.decode24(&res, r); CPPUNIT_ASSERT(ret); CPPUNIT_ASSERT((res >> 12) == 0b100100110110); } @@ -68,7 +68,7 @@ qa_golay24::errors_0() static inline uint32_t flip(uint32_t in, uint32_t n) { - if(!n || n > 24) { + if (!n || n > 24) { return in; } @@ -76,14 +76,14 @@ flip(uint32_t in, uint32_t n) std::mt19937 mt(rd()); std::uniform_int_distribution flip(0, 23); std::vector idx; - while(idx.size() < n) { + while (idx.size() < n) { uint8_t i = flip(mt); if (std::find(idx.begin(), idx.end(), i) == idx.end()) { idx.push_back(i); } } uint32_t mask = 0; - for(uint8_t i : idx) { + for (uint8_t i : idx) { mask |= (1 << i); } return in ^ mask; @@ -96,7 +96,7 @@ qa_golay24::errors_1() std::mt19937 mt(rd()); std::uniform_int_distribution uni(0, 0xFFFF); - for(size_t i = 0; i < 2048; i++) { + for (size_t i = 0; i < 2048; i++) { uint16_t x = uni(mt) & 0xFFF; golay24 gol; uint32_t coded = gol.encode12(x); @@ -106,14 +106,14 @@ qa_golay24::errors_1() uint32_t res; bool ret = gol.decode24(&res, coded); CPPUNIT_ASSERT(ret); - CPPUNIT_ASSERT((res >> 12)== x); + CPPUNIT_ASSERT((res >> 12) == x); coded = gol.encode12(x, false); /* Apply bit flip */ coder_error = flip(coded, 1); ret = gol.decode24(&res, coded); CPPUNIT_ASSERT(ret); - CPPUNIT_ASSERT((res & 0xFFF)== x); + CPPUNIT_ASSERT((res & 0xFFF) == x); } } @@ -124,7 +124,7 @@ qa_golay24::errors_3() std::mt19937 mt(rd()); std::uniform_int_distribution uni(0, 0xFFFF); - for(size_t i = 0; i < 2048; i++) { + for (size_t i = 0; i < 2048; i++) { uint16_t x = uni(mt) & 0xFFF; golay24 gol; uint32_t coded = gol.encode12(x); @@ -134,14 +134,14 @@ qa_golay24::errors_3() uint32_t res; bool ret = gol.decode24(&res, coded); CPPUNIT_ASSERT(ret); - CPPUNIT_ASSERT((res >> 12)== x); + CPPUNIT_ASSERT((res >> 12) == x); coded = gol.encode12(x, false); /* Apply bit flip */ coder_error = flip(coded, 3); ret = gol.decode24(&res, coded); CPPUNIT_ASSERT(ret); - CPPUNIT_ASSERT((res & 0xFFF)== x); + CPPUNIT_ASSERT((res & 0xFFF) == x); } } @@ -152,7 +152,7 @@ qa_golay24::errors_4() std::mt19937 mt(rd()); std::uniform_int_distribution uni(0, 0xFFFF); - for(size_t i = 0; i < 2048; i++) { + for (size_t i = 0; i < 2048; i++) { uint16_t x = uni(mt) & 0xFFF; golay24 gol; uint32_t coded = gol.encode12(x); @@ -161,16 +161,16 @@ qa_golay24::errors_4() uint32_t res; bool ret = gol.decode24(&res, coded); - if(ret) { - CPPUNIT_ASSERT((res >> 12)== x); + if (ret) { + CPPUNIT_ASSERT((res >> 12) == x); } coded = gol.encode12(x, false); /* Apply bit flip */ coder_error = flip(coded, 4); ret = gol.decode24(&res, coded); - if(ret) { - CPPUNIT_ASSERT((res & 0xFFF)== x); + if (ret) { + CPPUNIT_ASSERT((res & 0xFFF) == x); } } } diff --git a/lib/qa_golay24.h b/lib/qa_golay24.h index 7696f66..bc59caa 100644 --- a/lib/qa_golay24.h +++ b/lib/qa_golay24.h @@ -29,8 +29,7 @@ namespace gr { namespace satnogs { -class qa_golay24 : public CppUnit::TestCase -{ +class qa_golay24 : public CppUnit::TestCase { public: CPPUNIT_TEST_SUITE(qa_golay24); CPPUNIT_TEST(example_47); @@ -45,16 +44,16 @@ private: example_47(); void - errors_0 (); + errors_0(); void - errors_1 (); + errors_1(); void - errors_3 (); + errors_3(); void - errors_4 (); + errors_4(); }; } // namespace satnogs diff --git a/lib/qa_ieee802_15_4_variant_decoder.cc b/lib/qa_ieee802_15_4_variant_decoder.cc index 3018f70..8fb68a6 100644 --- a/lib/qa_ieee802_15_4_variant_decoder.cc +++ b/lib/qa_ieee802_15_4_variant_decoder.cc @@ -23,13 +23,11 @@ #include "qa_ieee802_15_4_variant_decoder.h" #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { void -qa_ieee802_15_4_variant_decoder::t1 () +qa_ieee802_15_4_variant_decoder::t1() { // Put test here } diff --git a/lib/qa_ieee802_15_4_variant_decoder.h b/lib/qa_ieee802_15_4_variant_decoder.h index a015020..325e20f 100644 --- a/lib/qa_ieee802_15_4_variant_decoder.h +++ b/lib/qa_ieee802_15_4_variant_decoder.h @@ -25,20 +25,19 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - class qa_ieee802_15_4_variant_decoder : public CppUnit::TestCase - { - public: - CPPUNIT_TEST_SUITE(qa_ieee802_15_4_variant_decoder); - CPPUNIT_TEST(t1); - CPPUNIT_TEST_SUITE_END(); +class qa_ieee802_15_4_variant_decoder : public CppUnit::TestCase { +public: + CPPUNIT_TEST_SUITE(qa_ieee802_15_4_variant_decoder); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END(); - private: - void t1(); - }; +private: + void t1(); +}; - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ #endif /* _QA_IEEE802_15_4_VARIANT_DECODER_H_ */ diff --git a/lib/qa_json_converter.cc b/lib/qa_json_converter.cc index 7be4d65..4e7d812 100644 --- a/lib/qa_json_converter.cc +++ b/lib/qa_json_converter.cc @@ -23,13 +23,11 @@ #include "qa_json_converter.h" #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { void -qa_json_converter::t1 () +qa_json_converter::t1() { // Put test here } diff --git a/lib/qa_json_converter.h b/lib/qa_json_converter.h index e824b7b..02cf10a 100644 --- a/lib/qa_json_converter.h +++ b/lib/qa_json_converter.h @@ -24,20 +24,19 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { -class qa_json_converter : public CppUnit::TestCase -{ -public:CPPUNIT_TEST_SUITE(qa_json_converter); - CPPUNIT_TEST(t1);CPPUNIT_TEST_SUITE_END() +class qa_json_converter : public CppUnit::TestCase { +public: + CPPUNIT_TEST_SUITE(qa_json_converter); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END() ; private: void - t1 (); + t1(); }; } /* namespace satnogs */ diff --git a/lib/qa_satnogs.h b/lib/qa_satnogs.h index 5cf4647..4ac1db2 100644 --- a/lib/qa_satnogs.h +++ b/lib/qa_satnogs.h @@ -25,9 +25,8 @@ #include -class __GR_ATTR_EXPORT qa_satnogs -{ - public: +class __GR_ATTR_EXPORT qa_satnogs { +public: static CppUnit::TestSuite *suite(); }; diff --git a/lib/qb50_deframer_impl.cc b/lib/qb50_deframer_impl.cc index 8bea79e..e8152e1 100644 --- a/lib/qb50_deframer_impl.cc +++ b/lib/qb50_deframer_impl.cc @@ -26,70 +26,68 @@ #include "qb50_deframer_impl.h" #include -namespace gr +namespace gr { +namespace satnogs { + +qb50_deframer::sptr +qb50_deframer::make(uint8_t wod_ssid) { - namespace satnogs - { + return gnuradio::get_initial_sptr(new qb50_deframer_impl(wod_ssid)); +} - qb50_deframer::sptr - qb50_deframer::make (uint8_t wod_ssid) - { - return gnuradio::get_initial_sptr (new qb50_deframer_impl (wod_ssid)); - } +void +qb50_deframer_impl::msg_handler(pmt::pmt_t msg) +{ + const uint8_t *frame; + uint8_t dest_ssid; + size_t frame_len; - void - qb50_deframer_impl::msg_handler (pmt::pmt_t msg) - { - const uint8_t *frame; - uint8_t dest_ssid; - size_t frame_len; + frame = (const uint8_t *) pmt::blob_data(msg); + frame_len = pmt::blob_length(msg); - frame = (const uint8_t *) pmt::blob_data(msg); - frame_len = pmt::blob_length(msg); + if (frame_len < AX25_MIN_ADDR_LEN) { + LOG_ERROR("Invalid AX.25 frame size"); + return; + } - if(frame_len < AX25_MIN_ADDR_LEN){ - LOG_ERROR("Invalid AX.25 frame size"); - return; - } + /* + * Get the destination SSID and decide in which port the frame should + * be forwarded. Also skip the leading headers and leave only the payload + */ + dest_ssid = ax25_get_dest_ssid(frame); + if (dest_ssid == d_wod_ssid) { + message_port_pub( + pmt::mp("wod"), + pmt::make_blob(frame + AX25_MIN_ADDR_LEN + 2, + frame_len - AX25_MIN_ADDR_LEN - 2)); + } + else { + message_port_pub( + pmt::mp("out"), + pmt::make_blob(frame + AX25_MIN_ADDR_LEN + 2, + frame_len - AX25_MIN_ADDR_LEN - 2)); + } +} - /* - * Get the destination SSID and decide in which port the frame should - * be forwarded. Also skip the leading headers and leave only the payload - */ - dest_ssid = ax25_get_dest_ssid(frame); - if(dest_ssid == d_wod_ssid){ - message_port_pub ( - pmt::mp ("wod"), - pmt::make_blob (frame + AX25_MIN_ADDR_LEN + 2, - frame_len - AX25_MIN_ADDR_LEN - 2)); - } - else{ - message_port_pub ( - pmt::mp ("out"), - pmt::make_blob (frame + AX25_MIN_ADDR_LEN + 2, - frame_len - AX25_MIN_ADDR_LEN - 2)); - } - } +/* + * The private constructor + */ +qb50_deframer_impl::qb50_deframer_impl(uint8_t wod_ssid) + : gr::block("qb50_deframer", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_wod_ssid(wod_ssid) +{ + message_port_register_in(pmt::mp("in")); + message_port_register_out(pmt::mp("out")); + message_port_register_out(pmt::mp("wod")); - /* - * The private constructor - */ - qb50_deframer_impl::qb50_deframer_impl(uint8_t wod_ssid) - : gr::block("qb50_deframer", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)), - d_wod_ssid(wod_ssid) - { - message_port_register_in(pmt::mp("in")); - message_port_register_out(pmt::mp("out")); - message_port_register_out(pmt::mp("wod")); - - set_msg_handler ( - pmt::mp ("in"), - boost::bind (&qb50_deframer_impl::msg_handler, this, _1)); - } + set_msg_handler( + pmt::mp("in"), + boost::bind(&qb50_deframer_impl::msg_handler, this, _1)); +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/qb50_deframer_impl.h b/lib/qb50_deframer_impl.h index bad2c74..3a03550 100644 --- a/lib/qb50_deframer_impl.h +++ b/lib/qb50_deframer_impl.h @@ -23,23 +23,20 @@ #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class qb50_deframer_impl : public qb50_deframer - { - private: - const uint8_t d_wod_ssid; +class qb50_deframer_impl : public qb50_deframer { +private: + const uint8_t d_wod_ssid; - void msg_handler(pmt::pmt_t msg); + void msg_handler(pmt::pmt_t msg); - public: - qb50_deframer_impl (uint8_t wod_ssid); - }; +public: + qb50_deframer_impl(uint8_t wod_ssid); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_QB50_DEFRAMER_IMPL_H */ diff --git a/lib/shift_reg.cc b/lib/shift_reg.cc index 2708033..3c34889 100644 --- a/lib/shift_reg.cc +++ b/lib/shift_reg.cc @@ -26,22 +26,22 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { /** * Creates a new shift register * @param len the number of the memory stages */ -shift_reg::shift_reg (size_t len) -: d_len(len), - d_reg(len, 0) +shift_reg::shift_reg(size_t len) + : d_len(len), + d_reg(len, 0) { - if(len < 1) { + if (len < 1) { throw std::invalid_argument("Shift register should contain at least one stage"); } } -shift_reg::~shift_reg () +shift_reg::~shift_reg() { } @@ -49,9 +49,9 @@ shift_reg::~shift_reg () * Sets all the memory stages to 0 */ void -shift_reg::reset () +shift_reg::reset() { - for(size_t i = 0; i < d_len; i++) { + for (size_t i = 0; i < d_len; i++) { d_reg[i] = 0; } } @@ -60,9 +60,9 @@ shift_reg::reset () * Sets all the memory stages to 1 */ void -shift_reg::set () +shift_reg::set() { - for(size_t i = 0; i < d_len; i++) { + for (size_t i = 0; i < d_len; i++) { d_reg[i] = 1; } } @@ -72,7 +72,7 @@ shift_reg::set () * @return the number of the memory stages of the shift register */ size_t -shift_reg::len () const +shift_reg::len() const { return d_len; } @@ -82,7 +82,7 @@ shift_reg::len () const * @return the number of the memory stages of the shift register */ size_t -shift_reg::size () const +shift_reg::size() const { return d_len; } @@ -92,54 +92,54 @@ shift_reg::size () const * @return the number of 1 bits */ size_t -shift_reg::count () +shift_reg::count() { size_t cnt = 0; - for(bool i : d_reg) { + for (bool i : d_reg) { cnt += i; } return cnt; } shift_reg -shift_reg::operator | (const shift_reg& rhs) +shift_reg::operator | (const shift_reg &rhs) { shift_reg ret(d_len); - for(size_t i = 0; i < d_len; i++) { + for (size_t i = 0; i < d_len; i++) { ret[i] = d_reg[i] | rhs[i]; } return ret; } shift_reg -shift_reg::operator & (const shift_reg& rhs) +shift_reg::operator & (const shift_reg &rhs) { shift_reg ret(d_len); - for(size_t i = 0; i < d_len; i++) { + for (size_t i = 0; i < d_len; i++) { ret[i] = d_reg[i] & rhs[i]; } return ret; } shift_reg -shift_reg::operator ^ (const shift_reg& rhs) +shift_reg::operator ^ (const shift_reg &rhs) { shift_reg ret(d_len); - for(size_t i = 0; i < d_len; i++) { + for (size_t i = 0; i < d_len; i++) { ret[i] = d_reg[i] ^ rhs[i]; } return ret; } -shift_reg& +shift_reg & shift_reg::operator >>= (bool bit) { push_front(bit); return *this; } -bool& -shift_reg::operator [] (size_t pos) +bool & +shift_reg::operator [](size_t pos) { return d_reg[pos]; } @@ -150,7 +150,7 @@ shift_reg::operator[](size_t pos) const return d_reg[pos]; } -shift_reg& +shift_reg & shift_reg::operator <<= (bool bit) { push_back(bit); @@ -162,7 +162,7 @@ shift_reg::operator <<= (bool bit) * @param bit the new value */ void -shift_reg::push_front (bool bit) +shift_reg::push_front(bool bit) { d_reg.pop_back(); d_reg.push_front(bit); @@ -173,7 +173,7 @@ shift_reg::push_front (bool bit) * @param bit the new value */ void -shift_reg::push_back (bool bit) +shift_reg::push_back(bool bit) { d_reg.pop_front(); d_reg.push_back(bit); @@ -184,7 +184,7 @@ shift_reg::push_back (bool bit) * @return the first element in the queue from right to left */ bool -shift_reg::front () +shift_reg::front() { return d_reg.front(); } @@ -194,15 +194,15 @@ shift_reg::front () * @return the last element in the queue from right to left */ bool -shift_reg::back () +shift_reg::back() { return d_reg.back(); } -std::ostream& -operator<<(std::ostream& os, const shift_reg& reg) +std::ostream & +operator<<(std::ostream &os, const shift_reg ®) { - for(bool bit : reg.d_reg) { + for (bool bit : reg.d_reg) { os << " " << bit; } return os; diff --git a/lib/tcp_rigctl_msg_source_impl.cc b/lib/tcp_rigctl_msg_source_impl.cc index 81a5d3f..f577011 100644 --- a/lib/tcp_rigctl_msg_source_impl.cc +++ b/lib/tcp_rigctl_msg_source_impl.cc @@ -40,316 +40,313 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +tcp_rigctl_msg_source::sptr +tcp_rigctl_msg_source::make(const std::string &addr, uint16_t port, + bool server_mode, size_t interval_ms, + size_t mtu) { - namespace satnogs - { - - tcp_rigctl_msg_source::sptr - tcp_rigctl_msg_source::make (const std::string& addr, uint16_t port, - bool server_mode, size_t interval_ms, - size_t mtu) - { - return gnuradio::get_initial_sptr ( - new tcp_rigctl_msg_source_impl (addr, port, server_mode, interval_ms, + return gnuradio::get_initial_sptr( + new tcp_rigctl_msg_source_impl(addr, port, server_mode, interval_ms, mtu)); - } +} - /* - * The private constructor - */ - tcp_rigctl_msg_source_impl::tcp_rigctl_msg_source_impl ( - const std::string& addr, uint16_t port, bool server_mode, - size_t interval_ms, size_t mtu) : - gr::block ("tcp_rigctl_msg_source", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_ip_addr (addr), - d_port (port), - d_is_server (server_mode), - d_interval_ms(interval_ms), - d_mtu (mtu), - d_running (true) - { - message_port_register_out (pmt::mp ("freq")); - if(d_is_server) { - d_thread = boost::shared_ptr ( - new boost::thread ( - boost::bind (&tcp_rigctl_msg_source_impl::rigctl_server, this))); - } - else{ - d_thread = boost::shared_ptr ( - new boost::thread ( - boost::bind (&tcp_rigctl_msg_source_impl::rigctl_client, this))); - } - } +/* + * The private constructor + */ +tcp_rigctl_msg_source_impl::tcp_rigctl_msg_source_impl( + const std::string &addr, uint16_t port, bool server_mode, + size_t interval_ms, size_t mtu) : + gr::block("tcp_rigctl_msg_source", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_ip_addr(addr), + d_port(port), + d_is_server(server_mode), + d_interval_ms(interval_ms), + d_mtu(mtu), + d_running(true) +{ + message_port_register_out(pmt::mp("freq")); + if (d_is_server) { + d_thread = boost::shared_ptr ( + new boost::thread( + boost::bind(&tcp_rigctl_msg_source_impl::rigctl_server, this))); + } + else { + d_thread = boost::shared_ptr ( + new boost::thread( + boost::bind(&tcp_rigctl_msg_source_impl::rigctl_client, this))); + } +} - static inline void - send_freq (int sock, uint64_t freq) - { - static char buf[512]; - snprintf (buf, 512, "%" PRIu64 "\n", freq); - send (sock, buf, strnlen (buf, 512), 0); - } +static inline void +send_freq(int sock, uint64_t freq) +{ + static char buf[512]; + snprintf(buf, 512, "%" PRIu64 "\n", freq); + send(sock, buf, strnlen(buf, 512), 0); +} - static inline void - send_report_code (int sock, int code) - { - static char buf[512]; - snprintf (buf, 512, "RPRT %d\n", code); - send (sock, buf, strnlen (buf, 512), 0); - } +static inline void +send_report_code(int sock, int code) +{ + static char buf[512]; + snprintf(buf, 512, "RPRT %d\n", code); + send(sock, buf, strnlen(buf, 512), 0); +} - static inline void - request_freq_msg (int sock) - { - static const char *cmd = "f\n"; - send (sock, cmd, strnlen(cmd, 2), 0); - } +static inline void +request_freq_msg(int sock) +{ + static const char *cmd = "f\n"; + send(sock, cmd, strnlen(cmd, 2), 0); +} - static inline void - send_quit(int sock) - { - static const char *cmd = "q\n"; - send (sock, cmd, strnlen(cmd, 2), 0); - } +static inline void +send_quit(int sock) +{ + static const char *cmd = "q\n"; + send(sock, cmd, strnlen(cmd, 2), 0); +} - void - tcp_rigctl_msg_source_impl::rigctl_client () - { - int sock; - struct sockaddr_in sin; - ssize_t ret; - uint8_t *buf; - double freq = 0.0; - int optval = 1; - struct timeval timeout; - timeout.tv_sec = 2; - timeout.tv_usec = 0; +void +tcp_rigctl_msg_source_impl::rigctl_client() +{ + int sock; + struct sockaddr_in sin; + ssize_t ret; + uint8_t *buf; + double freq = 0.0; + int optval = 1; + struct timeval timeout; + timeout.tv_sec = 2; + timeout.tv_usec = 0; - if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - perror ("opening UDP socket"); - exit (EXIT_FAILURE); - } + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror("opening UDP socket"); + exit(EXIT_FAILURE); + } - memset (&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons (d_port); - sin.sin_addr.s_addr = INADDR_ANY; + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(d_port); + sin.sin_addr.s_addr = INADDR_ANY; - if (inet_aton (d_ip_addr.c_str (), &(sin.sin_addr)) == 0) { - LOG_ERROR("Wrong IP address"); - close (sock); - exit (EXIT_FAILURE); - } + if (inet_aton(d_ip_addr.c_str(), &(sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close(sock); + exit(EXIT_FAILURE); + } - if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) != 0) { - LOG_ERROR("Could not connect at rigctl server %s", d_ip_addr.c_str()); - close (sock); - exit (EXIT_FAILURE); - } + if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) != 0) { + LOG_ERROR("Could not connect at rigctl server %s", d_ip_addr.c_str()); + close(sock); + exit(EXIT_FAILURE); + } + /* + * Apply the TCP_NODELAY option at the socket for a packet based + * behavior. + */ + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) + < 0) { + perror("TCP setsockopt TCP_NODELAY"); + shutdown(sock, SHUT_RDWR); + close(sock); + exit(EXIT_FAILURE); + } + + /* Set a reasonable timeout at the response from the server */ + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) + < 0) { + perror("TCP setsockopt SO_RCVTIMEO"); + shutdown(sock, SHUT_RDWR); + close(sock); + exit(EXIT_FAILURE); + } + + /* All good until now. Allocate buffer memory and proceed */ + buf = new uint8_t[d_mtu]; + sleep(2); + while (d_running) { + /* Request frequency from rigctl */ + request_freq_msg(sock); + ret = recv(sock, buf, d_mtu, 0); + if (ret > 0) { + freq = get_freq_from_buf(buf); /* - * Apply the TCP_NODELAY option at the socket for a packet based - * behavior. + * If the frequency is different than 0, then the parsed value + * is valid and an appropriate message can be generated + * + * NOTE: Comparison for equality in floats is a bit tricky. + * But here the get_freq_from_buf() will assign a 0.0 explicitly + * if something goes wrong. For this reason it is safe to compare + * the in-equality against 0.0. */ - if (setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) - < 0) { - perror ("TCP setsockopt TCP_NODELAY"); - shutdown(sock, SHUT_RDWR); - close(sock); - exit (EXIT_FAILURE); + if (freq != 0.0 && !std::isnan(freq)) { + message_port_pub(pmt::mp("freq"), pmt::from_double(freq)); } + } + boost::this_thread::sleep(boost::posix_time::milliseconds(d_interval_ms)); + } - /* Set a reasonable timeout at the response from the server */ - if (setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) - < 0) { - perror ("TCP setsockopt SO_RCVTIMEO"); - shutdown (sock, SHUT_RDWR); - close (sock); - exit (EXIT_FAILURE); - } + send_quit(sock); + shutdown(sock, SHUT_RDWR); + close(sock); + delete[] buf; + exit(EXIT_SUCCESS); +} - /* All good until now. Allocate buffer memory and proceed */ - buf = new uint8_t[d_mtu]; - sleep(2); - while (d_running) { - /* Request frequency from rigctl */ - request_freq_msg (sock); - ret = recv (sock, buf, d_mtu, 0); - if (ret > 0) { - freq = get_freq_from_buf (buf); - /* - * If the frequency is different than 0, then the parsed value - * is valid and an appropriate message can be generated - * - * NOTE: Comparison for equality in floats is a bit tricky. - * But here the get_freq_from_buf() will assign a 0.0 explicitly - * if something goes wrong. For this reason it is safe to compare - * the in-equality against 0.0. - */ - if (freq != 0.0 && !std::isnan(freq)) { - message_port_pub (pmt::mp ("freq"), pmt::from_double (freq)); - } - } - boost::this_thread::sleep(boost::posix_time::milliseconds(d_interval_ms)); - } +void +tcp_rigctl_msg_source_impl::rigctl_server() +{ + int sock; + int listen_sock; + struct sockaddr_in sin; + struct sockaddr client_addr; + socklen_t client_addr_len; + ssize_t ret; + uint8_t *buf; + double freq = 0.0; + uint64_t reported_freq = 0; + int error_code = 0; + int optval = 1; - send_quit(sock); - shutdown (sock, SHUT_RDWR); - close (sock); - delete[] buf; - exit (EXIT_SUCCESS); + if ((listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror("opening UDP socket"); + exit(EXIT_FAILURE); + } + + memset(&client_addr, 0, sizeof(struct sockaddr)); + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(d_port); + sin.sin_addr.s_addr = INADDR_ANY; + + if (inet_aton(d_ip_addr.c_str(), &(sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close(listen_sock); + exit(EXIT_FAILURE); + } + + if (bind(listen_sock, (struct sockaddr *) &sin, + sizeof(struct sockaddr_in)) == -1) { + perror("TCP bind"); + close(listen_sock); + exit(EXIT_FAILURE); + } + + if (listen(listen_sock, 1000) == -1) { + perror("TCP listen"); + close(listen_sock); + exit(EXIT_FAILURE); + } + + /* All good until now. Allocate buffer memory and proceed */ + buf = new uint8_t[d_mtu]; + + while (d_running) { + sock = accept(listen_sock, &client_addr, &client_addr_len); + if (sock <= 0) { + perror("TCP accept"); + exit(EXIT_FAILURE); } - void - tcp_rigctl_msg_source_impl::rigctl_server () - { - int sock; - int listen_sock; - struct sockaddr_in sin; - struct sockaddr client_addr; - socklen_t client_addr_len; - ssize_t ret; - uint8_t *buf; - double freq = 0.0; - uint64_t reported_freq = 0; - int error_code = 0; - int optval = 1; - - if ((listen_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - perror ("opening UDP socket"); - exit (EXIT_FAILURE); - } - - memset (&client_addr, 0, sizeof(struct sockaddr)); - memset (&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons (d_port); - sin.sin_addr.s_addr = INADDR_ANY; - - if (inet_aton (d_ip_addr.c_str (), &(sin.sin_addr)) == 0) { - LOG_ERROR("Wrong IP address"); - close (listen_sock); - exit (EXIT_FAILURE); - } - - if (bind (listen_sock, (struct sockaddr *) &sin, - sizeof(struct sockaddr_in)) == -1) { - perror ("TCP bind"); - close (listen_sock); - exit (EXIT_FAILURE); - } - - if (listen (listen_sock, 1000) == -1) { - perror ("TCP listen"); - close (listen_sock); - exit (EXIT_FAILURE); - } - - /* All good until now. Allocate buffer memory and proceed */ - buf = new uint8_t[d_mtu]; - - while (d_running) { - sock = accept (listen_sock, &client_addr, &client_addr_len); - if (sock <= 0) { - perror ("TCP accept"); - exit (EXIT_FAILURE); - } - - /* Apply the TCP_NODELAY option at the accepted socket */ - if (setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) - < 0) { - perror ("TCP setsockopt"); - shutdown(sock, SHUT_RDWR); - close(sock); - exit (EXIT_FAILURE); - } - - while ((ret = recv (sock, buf, d_mtu, 0)) > 0 && d_running) { - switch (buf[0]) - { - case 'F': - freq = get_freq_from_buf (buf + 2); - /* - * If the frequency is different than 0, then the parsed value - * is valid and an appropriate message can be generated - * - * NOTE: Comparison for equality in floats is a bit tricky. - * But here the get_freq_from_buf() will assign a 0.0 explicitly - * if something goes wrong. For this reason it is safe to compare - * the in-equality against 0.0. - */ - if (freq != 0.0) { - reported_freq = freq; - message_port_pub (pmt::mp ("freq"), pmt::from_double (freq)); - error_code = 0; - } - else { - error_code = -11; - } - /* Send the report code */ - send_report_code (sock, error_code); - break; - case 'f': - send_freq (sock, reported_freq); - break; - /* Terminate the connection and exit */ - case 'q': - send_report_code (sock, 0); - d_running = false; - break; - default: - LOG_WARN("Unsupported rigctl command"); - send_report_code (sock, -11); - } - } - shutdown (sock, SHUT_RDWR); - close (sock); - } - shutdown (listen_sock, SHUT_RDWR); - close (listen_sock); - delete[] buf; - exit (EXIT_SUCCESS); + /* Apply the TCP_NODELAY option at the accepted socket */ + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)) + < 0) { + perror("TCP setsockopt"); + shutdown(sock, SHUT_RDWR); + close(sock); + exit(EXIT_FAILURE); } - /** - * Parses the string in the \p buf trying to extract a frequency reading - * until the newline character - * @param buf the buffer containing a line with the target frequency - * @return the frequency converted into double - */ - double - tcp_rigctl_msg_source_impl::get_freq_from_buf (const uint8_t* buf) - { - long long int f; - char *end; - f = strtoll ((char *) buf, &end, 10); - - /* Check for various possible errors */ - if ((errno == ERANGE && (f == LLONG_MAX || f == LLONG_MIN)) - || (errno != 0 && f == 0)) { - LOG_WARN("Invalid rigctl command"); - f = 0; + while ((ret = recv(sock, buf, d_mtu, 0)) > 0 && d_running) { + switch (buf[0]) { + case 'F': + freq = get_freq_from_buf(buf + 2); + /* + * If the frequency is different than 0, then the parsed value + * is valid and an appropriate message can be generated + * + * NOTE: Comparison for equality in floats is a bit tricky. + * But here the get_freq_from_buf() will assign a 0.0 explicitly + * if something goes wrong. For this reason it is safe to compare + * the in-equality against 0.0. + */ + if (freq != 0.0) { + reported_freq = freq; + message_port_pub(pmt::mp("freq"), pmt::from_double(freq)); + error_code = 0; + } + else { + error_code = -11; + } + /* Send the report code */ + send_report_code(sock, error_code); + break; + case 'f': + send_freq(sock, reported_freq); + break; + /* Terminate the connection and exit */ + case 'q': + send_report_code(sock, 0); + d_running = false; + break; + default: + LOG_WARN("Unsupported rigctl command"); + send_report_code(sock, -11); } - - if ((char *) buf == end) { - LOG_WARN("Invalid rigctl command"); - f = 0; - } - - return (double) f; } + shutdown(sock, SHUT_RDWR); + close(sock); + } + shutdown(listen_sock, SHUT_RDWR); + close(listen_sock); + delete[] buf; + exit(EXIT_SUCCESS); +} - /* - * Our virtual destructor. - */ - tcp_rigctl_msg_source_impl::~tcp_rigctl_msg_source_impl () - { - d_running = false; - d_thread->join (); - } +/** + * Parses the string in the \p buf trying to extract a frequency reading + * until the newline character + * @param buf the buffer containing a line with the target frequency + * @return the frequency converted into double + */ +double +tcp_rigctl_msg_source_impl::get_freq_from_buf(const uint8_t *buf) +{ + long long int f; + char *end; + f = strtoll((char *) buf, &end, 10); - } /* namespace satnogs */ + /* Check for various possible errors */ + if ((errno == ERANGE && (f == LLONG_MAX || f == LLONG_MIN)) + || (errno != 0 && f == 0)) { + LOG_WARN("Invalid rigctl command"); + f = 0; + } + + if ((char *) buf == end) { + LOG_WARN("Invalid rigctl command"); + f = 0; + } + + return (double) f; +} + +/* + * Our virtual destructor. + */ +tcp_rigctl_msg_source_impl::~tcp_rigctl_msg_source_impl() +{ + d_running = false; + d_thread->join(); +} + +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/tcp_rigctl_msg_source_impl.h b/lib/tcp_rigctl_msg_source_impl.h index 63b4e45..700a460 100644 --- a/lib/tcp_rigctl_msg_source_impl.h +++ b/lib/tcp_rigctl_msg_source_impl.h @@ -23,40 +23,37 @@ #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class tcp_rigctl_msg_source_impl : public tcp_rigctl_msg_source - { - private: - const std::string d_ip_addr; - const uint16_t d_port; - const bool d_is_server; - const size_t d_interval_ms; - const size_t d_mtu; - bool d_running; - boost::shared_ptr d_thread; +class tcp_rigctl_msg_source_impl : public tcp_rigctl_msg_source { +private: + const std::string d_ip_addr; + const uint16_t d_port; + const bool d_is_server; + const size_t d_interval_ms; + const size_t d_mtu; + bool d_running; + boost::shared_ptr d_thread; - void - rigctl_server(); + void + rigctl_server(); - void - rigctl_client(); + void + rigctl_client(); - double - get_freq_from_buf(const uint8_t *buf); + double + get_freq_from_buf(const uint8_t *buf); - public: - tcp_rigctl_msg_source_impl (const std::string& addr, uint16_t port, - bool server_mode, size_t interval_ms, - size_t mtu); - ~tcp_rigctl_msg_source_impl (); - }; +public: + tcp_rigctl_msg_source_impl(const std::string &addr, uint16_t port, + bool server_mode, size_t interval_ms, + size_t mtu); + ~tcp_rigctl_msg_source_impl(); +}; - } // namespace satnogs - } // namespace gr +} // namespace satnogs +} // namespace gr #endif /* INCLUDED_SATNOGS_TCP_RIGCTL_MSG_SOURCE_IMPL_H */ diff --git a/lib/test_satnogs.cc b/lib/test_satnogs.cc index cb7bf0d..db8798f 100644 --- a/lib/test_satnogs.cc +++ b/lib/test_satnogs.cc @@ -38,7 +38,7 @@ #include int -main (int argc, char **argv) +main(int argc, char **argv) { CppUnit::TestResultCollector result; CppUnit::BriefTestProgressListener progressListener; diff --git a/lib/udp_msg_sink_impl.cc b/lib/udp_msg_sink_impl.cc index d7f116a..238041e 100644 --- a/lib/udp_msg_sink_impl.cc +++ b/lib/udp_msg_sink_impl.cc @@ -27,68 +27,68 @@ #include namespace gr { - namespace satnogs { +namespace satnogs { - udp_msg_sink::sptr - udp_msg_sink::make(const std::string& addr, uint16_t port, size_t mtu) - { - return gnuradio::get_initial_sptr - (new udp_msg_sink_impl(addr, port, mtu)); - } +udp_msg_sink::sptr +udp_msg_sink::make(const std::string &addr, uint16_t port, size_t mtu) +{ + return gnuradio::get_initial_sptr + (new udp_msg_sink_impl(addr, port, mtu)); +} - /* - * The private constructor - */ - udp_msg_sink_impl::udp_msg_sink_impl (const std::string& addr, - uint16_t port, size_t mtu) : - gr::block ("udp_msg_sink", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_iface_addr(addr), - d_udp_port(port), - d_mtu(mtu) - { - message_port_register_in(pmt::mp("in")); - set_msg_handler(pmt::mp("in"), - boost::bind(&udp_msg_sink_impl::msg_handler, - this, _1)); +/* + * The private constructor + */ +udp_msg_sink_impl::udp_msg_sink_impl(const std::string &addr, + uint16_t port, size_t mtu) : + gr::block("udp_msg_sink", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_iface_addr(addr), + d_udp_port(port), + d_mtu(mtu) +{ + message_port_register_in(pmt::mp("in")); + set_msg_handler(pmt::mp("in"), + boost::bind(&udp_msg_sink_impl::msg_handler, + this, _1)); - /* Open the socket */ - if ((d_sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { - perror ("opening UDP socket"); - throw std::runtime_error("Could not open UDP socket"); - } + /* Open the socket */ + if ((d_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + perror("opening UDP socket"); + throw std::runtime_error("Could not open UDP socket"); + } - memset (&d_sin, 0, sizeof(struct sockaddr_in)); - d_sin.sin_family = AF_INET; - d_sin.sin_port = htons (d_udp_port); + memset(&d_sin, 0, sizeof(struct sockaddr_in)); + d_sin.sin_family = AF_INET; + d_sin.sin_port = htons(d_udp_port); - if( inet_aton(d_iface_addr.c_str(), &(d_sin.sin_addr)) == 0){ - LOG_ERROR("Wrong IP address"); - close(d_sock); - throw std::runtime_error("Wrong IP address"); - } - } + if (inet_aton(d_iface_addr.c_str(), &(d_sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close(d_sock); + throw std::runtime_error("Wrong IP address"); + } +} - void - udp_msg_sink_impl::msg_handler (pmt::pmt_t msg) - { - const void *buf = pmt::blob_data(msg); - size_t len = pmt::blob_length(msg); +void +udp_msg_sink_impl::msg_handler(pmt::pmt_t msg) +{ + const void *buf = pmt::blob_data(msg); + size_t len = pmt::blob_length(msg); - if(len < d_mtu){ - sendto(d_sock, buf, len, 0, (sockaddr *) &d_sin, sizeof(sockaddr_in)); - } - } + if (len < d_mtu) { + sendto(d_sock, buf, len, 0, (sockaddr *) &d_sin, sizeof(sockaddr_in)); + } +} - /* - * Our virtual destructor. - */ - udp_msg_sink_impl::~udp_msg_sink_impl() - { - close(d_sock); - } +/* + * Our virtual destructor. + */ +udp_msg_sink_impl::~udp_msg_sink_impl() +{ + close(d_sock); +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/udp_msg_sink_impl.h b/lib/udp_msg_sink_impl.h index 65e002d..5258697 100644 --- a/lib/udp_msg_sink_impl.h +++ b/lib/udp_msg_sink_impl.h @@ -31,28 +31,25 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class udp_msg_sink_impl : public udp_msg_sink - { - private: - const std::string d_iface_addr; - const uint16_t d_udp_port; - const size_t d_mtu; - int d_sock; - struct sockaddr_in d_sin; +class udp_msg_sink_impl : public udp_msg_sink { +private: + const std::string d_iface_addr; + const uint16_t d_udp_port; + const size_t d_mtu; + int d_sock; + struct sockaddr_in d_sin; - void msg_handler(pmt::pmt_t msg); + void msg_handler(pmt::pmt_t msg); - public: - udp_msg_sink_impl (const std::string& addr, uint16_t port, size_t mtu); - ~udp_msg_sink_impl (); - }; +public: + udp_msg_sink_impl(const std::string &addr, uint16_t port, size_t mtu); + ~udp_msg_sink_impl(); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_UDP_MSG_SINK_IMPL_H */ diff --git a/lib/udp_msg_source_impl.cc b/lib/udp_msg_source_impl.cc index 34d7a1e..ce05f0b 100644 --- a/lib/udp_msg_source_impl.cc +++ b/lib/udp_msg_source_impl.cc @@ -33,130 +33,128 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +udp_msg_source::sptr +udp_msg_source::make(const std::string &addr, uint16_t port, size_t mtu, + size_t type) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new udp_msg_source_impl(addr, port, mtu, type)); +} - udp_msg_source::sptr - udp_msg_source::make (const std::string& addr, uint16_t port, size_t mtu, - size_t type) - { - return gnuradio::get_initial_sptr ( - new udp_msg_source_impl (addr, port, mtu, type)); - } +/* + * The private constructor + */ +udp_msg_source_impl::udp_msg_source_impl(const std::string &addr, + uint16_t port, size_t mtu, + size_t type) : + gr::block("udp_msg_source", gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_iface_addr(addr), + d_udp_port(port), + d_mtu(mtu), + d_type(type), + d_running(true) +{ + message_port_register_out(pmt::mp("msg")); + boost::shared_ptr ( + new boost::thread( + boost::bind(&udp_msg_source_impl::udp_msg_accepter, this))); +} - /* - * The private constructor - */ - udp_msg_source_impl::udp_msg_source_impl (const std::string& addr, - uint16_t port, size_t mtu, - size_t type) : - gr::block ("udp_msg_source", gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), - d_iface_addr (addr), - d_udp_port (port), - d_mtu (mtu), - d_type (type), - d_running (true) - { - message_port_register_out (pmt::mp ("msg")); - boost::shared_ptr ( - new boost::thread ( - boost::bind (&udp_msg_source_impl::udp_msg_accepter, this))); - } +void +udp_msg_source_impl::udp_msg_accepter() +{ + int sock; + struct sockaddr_in sin; + struct sockaddr client_addr; + socklen_t client_addr_len; + ssize_t ret; + uint8_t *buf; + uint32_t bytes_num; + uint32_t uint_val; + uint32_t int_val; - void - udp_msg_source_impl::udp_msg_accepter () - { - int sock; - struct sockaddr_in sin; - struct sockaddr client_addr; - socklen_t client_addr_len; - ssize_t ret; - uint8_t *buf; - uint32_t bytes_num; - uint32_t uint_val; - uint32_t int_val; + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + perror("opening UDP socket"); + exit(EXIT_FAILURE); + } - if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { - perror ("opening UDP socket"); - exit (EXIT_FAILURE); - } + memset(&client_addr, 0, sizeof(struct sockaddr)); + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(d_udp_port); - memset (&client_addr, 0, sizeof(struct sockaddr)); - memset (&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons (d_udp_port); + if (inet_aton(d_iface_addr.c_str(), &(sin.sin_addr)) == 0) { + LOG_ERROR("Wrong IP address"); + close(sock); + exit(EXIT_FAILURE); + } - if (inet_aton (d_iface_addr.c_str (), &(sin.sin_addr)) == 0) { - LOG_ERROR("Wrong IP address"); - close (sock); - exit (EXIT_FAILURE); - } + if (bind(sock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) + == -1) { + perror("UDP bind"); + close(sock); + exit(EXIT_FAILURE); + } - if (bind (sock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) - == -1) { - perror ("UDP bind"); - close (sock); - exit (EXIT_FAILURE); - } + /* All good until now. Allocate buffer memory and proceed */ + buf = new uint8_t[d_mtu]; - /* All good until now. Allocate buffer memory and proceed */ - buf = new uint8_t[d_mtu]; - - while (d_running) { - ret = recvfrom (sock, buf, d_mtu, 0, &client_addr, &client_addr_len); - if (ret > 0) { - bytes_num = (uint32_t) ret; - switch(d_type){ - case 0: - message_port_pub (pmt::mp ("msg"), pmt::make_blob (buf, bytes_num)); - break; - case 1: - if(bytes_num < sizeof(uint32_t)){ - continue; - } - memcpy(&uint_val, buf, sizeof(uint32_t)); - message_port_pub (pmt::mp ("msg"), - pmt::from_uint64 (ntohl (uint_val))); - break; - case 2: - if (bytes_num < sizeof(int32_t)) { - continue; - } - memcpy(&int_val, buf, sizeof(int32_t)); - message_port_pub (pmt::mp ("msg"), - pmt::from_long (ntohl (int_val))); - break; - default: - LOG_ERROR("Unsupported message type"); - close (sock); - delete[] buf; - exit (EXIT_FAILURE); - } + while (d_running) { + ret = recvfrom(sock, buf, d_mtu, 0, &client_addr, &client_addr_len); + if (ret > 0) { + bytes_num = (uint32_t) ret; + switch (d_type) { + case 0: + message_port_pub(pmt::mp("msg"), pmt::make_blob(buf, bytes_num)); + break; + case 1: + if (bytes_num < sizeof(uint32_t)) { + continue; } - else { - perror ("UDP recvfrom"); - close (sock); - delete[] buf; - exit (EXIT_FAILURE); + memcpy(&uint_val, buf, sizeof(uint32_t)); + message_port_pub(pmt::mp("msg"), + pmt::from_uint64(ntohl(uint_val))); + break; + case 2: + if (bytes_num < sizeof(int32_t)) { + continue; } + memcpy(&int_val, buf, sizeof(int32_t)); + message_port_pub(pmt::mp("msg"), + pmt::from_long(ntohl(int_val))); + break; + default: + LOG_ERROR("Unsupported message type"); + close(sock); + delete[] buf; + exit(EXIT_FAILURE); } - close (sock); + } + else { + perror("UDP recvfrom"); + close(sock); delete[] buf; - exit (EXIT_SUCCESS); + exit(EXIT_FAILURE); } + } + close(sock); + delete[] buf; + exit(EXIT_SUCCESS); +} - /* - * Our virtual destructor. - */ - udp_msg_source_impl::~udp_msg_source_impl () - { - d_running = false; - d_thread->join (); - } +/* + * Our virtual destructor. + */ +udp_msg_source_impl::~udp_msg_source_impl() +{ + d_running = false; + d_thread->join(); +} - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/udp_msg_source_impl.h b/lib/udp_msg_source_impl.h index 4c4c810..eb2820a 100644 --- a/lib/udp_msg_source_impl.h +++ b/lib/udp_msg_source_impl.h @@ -24,31 +24,28 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class udp_msg_source_impl : public udp_msg_source - { - private: - const std::string d_iface_addr; - const uint16_t d_udp_port; - const size_t d_mtu; - const size_t d_type; - bool d_running; - boost::shared_ptr d_thread; +class udp_msg_source_impl : public udp_msg_source { +private: + const std::string d_iface_addr; + const uint16_t d_udp_port; + const size_t d_mtu; + const size_t d_type; + bool d_running; + boost::shared_ptr d_thread; - void - udp_msg_accepter (); + void + udp_msg_accepter(); - public: - udp_msg_source_impl (const std::string& addr, uint16_t port, - size_t mtu, size_t type); - ~udp_msg_source_impl (); - }; +public: + udp_msg_source_impl(const std::string &addr, uint16_t port, + size_t mtu, size_t type); + ~udp_msg_source_impl(); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_UDP_MSG_SOURCE_IMPL_H */ diff --git a/lib/upsat_fsk_frame_encoder_impl.cc b/lib/upsat_fsk_frame_encoder_impl.cc index 9661940..44141b0 100644 --- a/lib/upsat_fsk_frame_encoder_impl.cc +++ b/lib/upsat_fsk_frame_encoder_impl.cc @@ -29,386 +29,382 @@ #include #include -namespace gr +namespace gr { +namespace satnogs { + +upsat_fsk_frame_encoder::sptr +upsat_fsk_frame_encoder::make(const std::vector &preamble, + const std::vector &sync_word, + bool append_crc, bool whitening, + bool manchester, bool msb_first, + bool ax25_format, + const std::string &ax25_dest_addr, + uint8_t ax25_dest_ssid, + const std::string &ax25_src_addr, + uint8_t ax25_src_ssid, + size_t settling_samples) { - namespace satnogs - { + return gnuradio::get_initial_sptr( + new upsat_fsk_frame_encoder_impl(preamble, sync_word, + append_crc, + whitening, manchester, + msb_first, ax25_format, + ax25_src_addr, ax25_src_ssid, + ax25_dest_addr, ax25_dest_ssid, + settling_samples)); +} - upsat_fsk_frame_encoder::sptr - upsat_fsk_frame_encoder::make (const std::vector& preamble, - const std::vector& sync_word, - bool append_crc, bool whitening, - bool manchester, bool msb_first, - bool ax25_format, - const std::string& ax25_dest_addr, - uint8_t ax25_dest_ssid, - const std::string& ax25_src_addr, - uint8_t ax25_src_ssid, - size_t settling_samples) - { - return gnuradio::get_initial_sptr ( - new upsat_fsk_frame_encoder_impl (preamble, sync_word, - append_crc, - whitening, manchester, - msb_first, ax25_format, - ax25_src_addr, ax25_src_ssid, - ax25_dest_addr, ax25_dest_ssid, - settling_samples)); +/* + * The private constructor + */ +upsat_fsk_frame_encoder_impl::upsat_fsk_frame_encoder_impl( + const std::vector &preamble, + const std::vector &sync_word, + bool append_crc, bool whitening, + bool manchester, bool msb_first, + bool ax25_format, + const std::string &ax25_dest_addr, + uint8_t ax25_dest_ssid, + const std::string &ax25_src_addr, + uint8_t ax25_src_ssid, + size_t settling_samples) : + gr::sync_block("upsat_fsk_frame_encoder", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, 1, sizeof(float))), + d_preamble(preamble), + d_preamble_len(preamble.size()), + d_sync_word(sync_word), + d_sync_word_len(sync_word.size()), + d_append_crc(append_crc), + d_whitening(whitening), + d_manchester(manchester), + d_msb_first(msb_first), + d_is_ax25(ax25_format), + d_max_pdu_len(d_preamble_len + d_sync_word_len + sizeof(uint8_t) + + UPSAT_MAX_FRAME_LEN + sizeof(uint16_t)), + d_settling_samples(settling_samples), + d_encoded(0), + d_pdu_len(0), + d_scrambler(0x1001, 0x1FF, 17) +{ + /* Simplify the logic of the output samples handling */ + set_output_multiple(8); + message_port_register_in(pmt::mp("pdu")); + /* + * Allocate memory for the maximum possible frame WITH all headers and + * tail fields + * +-------------+----------+--------+--------------------------+------+ + * | Preamble | SFD | LENGTH | PDU | CRC | + * +-------------+----------+--------+--------------------------+------+ + * User def. User def. 1B 1-255 B 2 B + */ + d_pdu = new uint8_t[d_max_pdu_len]; + + + if (d_is_ax25) { + d_ax25_addr = new uint8_t[AX25_MAX_ADDR_LEN]; + /* One useful bit per byte for the AX.25 buffer */ + d_ax25_pdu = new uint8_t[2 * d_max_pdu_len * 8]; + d_ax25_tmp_buf = new uint8_t[d_max_pdu_len * 2]; + d_ax25_addr_len = ax25_create_addr_field(d_ax25_addr, ax25_dest_addr, + ax25_dest_ssid, ax25_src_addr, + ax25_src_ssid); + } + + d_pdu_encoded = new float[d_max_pdu_len * 8 + d_settling_samples]; + + /* Copy the preamble at the start of the pdu */ + memcpy(d_pdu, d_preamble.data(), d_preamble_len); + memcpy(d_pdu + d_preamble_len, d_sync_word.data(), d_sync_word_len); +} + +/* + * Our virtual destructor. + */ +upsat_fsk_frame_encoder_impl::~upsat_fsk_frame_encoder_impl() +{ + delete [] d_pdu; + delete [] d_pdu_encoded; + if (d_is_ax25) { + delete [] d_ax25_addr; + delete [] d_ax25_pdu; + delete [] d_ax25_tmp_buf; + } +} + +inline void +upsat_fsk_frame_encoder_impl::map_msb_first(float *out, size_t nsamples_out) +{ + size_t i; + register uint8_t b; + for (i = 0; i < nsamples_out; i += 8) { + b = d_pdu[d_encoded + i / 8]; + out[i] = ((b >> 7) * 2.0f) - 1.0f; + out[i + 1] = (((b >> 6) & 0x1) * 2.0f) - 1.0f; + out[i + 2] = (((b >> 5) & 0x1) * 2.0f) - 1.0f; + out[i + 3] = (((b >> 4) & 0x1) * 2.0f) - 1.0f; + out[i + 4] = (((b >> 3) & 0x1) * 2.0f) - 1.0f; + out[i + 5] = (((b >> 2) & 0x1) * 2.0f) - 1.0f; + out[i + 6] = (((b >> 1) & 0x1) * 2.0f) - 1.0f; + out[i + 7] = ((b & 0x1) * 2.0f) - 1.0f; + } +} + +inline void +upsat_fsk_frame_encoder_impl::map_lsb_first(float *out, size_t nsamples_out) +{ + size_t i; + register uint8_t b; + for (i = 0; i < nsamples_out; i += 8) { + b = d_pdu[d_encoded + i / 8]; + out[i + 7] = ((b >> 7) * 2.0f) - 1.0f; + out[i + 6] = (((b >> 6) & 0x1) * 2.0f) - 1.0f; + out[i + 5] = (((b >> 5) & 0x1) * 2.0f) - 1.0f; + out[i + 4] = (((b >> 4) & 0x1) * 2.0f) - 1.0f; + out[i + 3] = (((b >> 3) & 0x1) * 2.0f) - 1.0f; + out[i + 2] = (((b >> 2) & 0x1) * 2.0f) - 1.0f; + out[i + 1] = (((b >> 1) & 0x1) * 2.0f) - 1.0f; + out[i] = ((b & 0x1) * 2.0f) - 1.0f; + } +} + +inline void +upsat_fsk_frame_encoder_impl::add_sob(uint64_t item) +{ + static const pmt::pmt_t sob_key = pmt::string_to_symbol("tx_sob"); + static const pmt::pmt_t value = pmt::PMT_T; + static const pmt::pmt_t srcid = pmt::string_to_symbol(alias()); + add_item_tag(0, item, sob_key, value, srcid); +} + +inline void +upsat_fsk_frame_encoder_impl::add_eob(uint64_t item) +{ + static const pmt::pmt_t eob_key = pmt::string_to_symbol("tx_eob"); + static const pmt::pmt_t value = pmt::PMT_T; + static const pmt::pmt_t srcid = pmt::string_to_symbol(alias()); + add_item_tag(0, item, eob_key, value, srcid); +} + +inline int +upsat_fsk_frame_encoder_impl::raw_frame_handling(float *out, + int noutput_items) +{ + uint16_t crc; + size_t min_available; + pmt::pmt_t pdu; + + /* + * If the whole previous frame has been successfully sent, block waiting + * for a new one + */ + if (d_encoded == 0) { + pdu = delete_head_blocking(pmt::mp("pdu")); + d_pdu_len = pmt::blob_length(pdu); + + if (d_pdu_len > UPSAT_MAX_FRAME_LEN) { + LOG_ERROR("PDU is greater than the supported. Dropping the PDU"); + return 0; + } + /* + * Set the frame length at the corresponding field. + * NOTE: The frame length is calculated taking consideration only + * the address field (if exists) and the payload. Length and CRC fields + * are NOT included. + */ + d_pdu[d_preamble_len + d_sync_word_len] = (uint8_t) d_pdu_len; + + /* Append the variable length PDU */ + memcpy(d_pdu + d_preamble_len + d_sync_word_len + 1, + pmt::blob_data(pdu), d_pdu_len); + + /* If it is necessary calculate and append the CRC */ + if (d_append_crc) { + crc = crc::crc16_ccitt(d_pdu + d_preamble_len + d_sync_word_len, + d_pdu_len + 1); + /* CRC must be transmitted MSB first */ + crc = htons(crc); + memcpy(d_pdu + d_preamble_len + d_sync_word_len + 1 + d_pdu_len, + &crc, sizeof(uint16_t)); + d_pdu_len += sizeof(uint16_t); } /* - * The private constructor + * Whitening is performed on all bytes except preamble and SYNC fields */ - upsat_fsk_frame_encoder_impl::upsat_fsk_frame_encoder_impl ( - const std::vector& preamble, - const std::vector& sync_word, - bool append_crc, bool whitening, - bool manchester, bool msb_first, - bool ax25_format, - const std::string& ax25_dest_addr, - uint8_t ax25_dest_ssid, - const std::string& ax25_src_addr, - uint8_t ax25_src_ssid, - size_t settling_samples) : - gr::sync_block ("upsat_fsk_frame_encoder", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (1, 1, sizeof(float))), - d_preamble (preamble), - d_preamble_len (preamble.size ()), - d_sync_word (sync_word), - d_sync_word_len (sync_word.size ()), - d_append_crc(append_crc), - d_whitening(whitening), - d_manchester(manchester), - d_msb_first(msb_first), - d_is_ax25(ax25_format), - d_max_pdu_len(d_preamble_len + d_sync_word_len + sizeof(uint8_t) - + UPSAT_MAX_FRAME_LEN + sizeof(uint16_t)), - d_settling_samples(settling_samples), - d_encoded(0), - d_pdu_len(0), - d_scrambler(0x1001, 0x1FF, 17) - { - /* Simplify the logic of the output samples handling */ - set_output_multiple(8); - message_port_register_in (pmt::mp ("pdu")); - /* - * Allocate memory for the maximum possible frame WITH all headers and - * tail fields - * +-------------+----------+--------+--------------------------+------+ - * | Preamble | SFD | LENGTH | PDU | CRC | - * +-------------+----------+--------+--------------------------+------+ - * User def. User def. 1B 1-255 B 2 B - */ - d_pdu = new uint8_t[d_max_pdu_len]; - - - if(d_is_ax25){ - d_ax25_addr = new uint8_t[AX25_MAX_ADDR_LEN]; - /* One useful bit per byte for the AX.25 buffer */ - d_ax25_pdu = new uint8_t[2 * d_max_pdu_len * 8]; - d_ax25_tmp_buf = new uint8_t[d_max_pdu_len * 2]; - d_ax25_addr_len = ax25_create_addr_field (d_ax25_addr, ax25_dest_addr, - ax25_dest_ssid, ax25_src_addr, - ax25_src_ssid); - } - - d_pdu_encoded = new float[d_max_pdu_len*8 + d_settling_samples]; - - /* Copy the preamble at the start of the pdu */ - memcpy(d_pdu, d_preamble.data(), d_preamble_len); - memcpy(d_pdu + d_preamble_len, d_sync_word.data(), d_sync_word_len); + if (d_whitening) { + d_scrambler.reset(); + d_scrambler.scramble(d_pdu + d_preamble_len + d_sync_word_len, + d_pdu + d_preamble_len + d_sync_word_len, + d_pdu_len + 1); } + d_pdu_len += d_preamble_len + d_sync_word_len + 1; + /* - * Our virtual destructor. + * NRZ Encode the whole frame */ - upsat_fsk_frame_encoder_impl::~upsat_fsk_frame_encoder_impl () - { - delete [] d_pdu; - delete [] d_pdu_encoded; - if(d_is_ax25) { - delete [] d_ax25_addr; - delete [] d_ax25_pdu; - delete [] d_ax25_tmp_buf; - } + if (d_msb_first) { + map_msb_first(d_pdu_encoded, d_pdu_len * 8); + } + else { + map_lsb_first(d_pdu_encoded, d_pdu_len * 8); } - inline void - upsat_fsk_frame_encoder_impl::map_msb_first(float *out, size_t nsamples_out) - { - size_t i; - register uint8_t b; - for(i = 0; i < nsamples_out; i+=8) - { - b = d_pdu[d_encoded + i/8]; - out[i] = ((b >> 7 ) * 2.0f) - 1.0f; - out[i + 1] = (( (b >> 6 ) & 0x1) * 2.0f) - 1.0f; - out[i + 2] = (( (b >> 5 ) & 0x1) * 2.0f) - 1.0f; - out[i + 3] = (( (b >> 4 ) & 0x1) * 2.0f) - 1.0f; - out[i + 4] = (( (b >> 3 ) & 0x1) * 2.0f) - 1.0f; - out[i + 5] = (( (b >> 2 ) & 0x1) * 2.0f) - 1.0f; - out[i + 6] = (( (b >> 1 ) & 0x1) * 2.0f) - 1.0f; - out[i + 7] = ((b & 0x1) * 2.0f) - 1.0f; - } + /* Reset the settling trailing samples */ + memset(d_pdu_encoded + d_pdu_len * 8, 0, + d_settling_samples * sizeof(float)); + + /* The new frame now has a bigger size of course*/ + d_pdu_len += d_settling_samples / 8; + + /* Start of burst */ + add_sob(nitems_written(0)); + } + + noutput_items = std::max(0, noutput_items); + min_available = std::min((size_t) noutput_items, + (d_pdu_len - d_encoded) * 8); + + memcpy(out, d_pdu_encoded + d_encoded * 8, + min_available * sizeof(float)); + d_encoded += min_available / 8; + + /* End of the frame reached */ + if (d_encoded == d_pdu_len) { + add_eob(nitems_written(0) + min_available - 1); + d_encoded = 0; + } + + return min_available; +} + +inline int +upsat_fsk_frame_encoder_impl::ax25_frame_handling(float *out, + int noutput_items) +{ + uint16_t crc; + size_t min_available; + pmt::pmt_t pdu; + size_t len; + size_t encoded_len; + ax25_encode_status_t status; + size_t extra_bits; + size_t i; + uint8_t len_field; + + /* + * If the whole previous frame has been successfully sent, block waiting + * for a new one + */ + if (d_encoded == 0) { + /* Reset the buffer */ + memset(d_ax25_pdu, 0, 2 * d_max_pdu_len * 8); + memset(d_pdu_encoded, 0, d_max_pdu_len * 8 * sizeof(float)); + pdu = delete_head_blocking(pmt::mp("pdu")); + d_pdu_len = pmt::blob_length(pdu); + + if (d_pdu_len > UPSAT_MAX_FRAME_LEN) { + LOG_ERROR("PDU is greater than the supported. Dropping the PDU"); + return 0; } - inline void - upsat_fsk_frame_encoder_impl::map_lsb_first(float *out, size_t nsamples_out) - { - size_t i; - register uint8_t b; - for(i = 0; i < nsamples_out; i+=8) - { - b = d_pdu[d_encoded + i/8]; - out[i + 7] = ((b >> 7 ) * 2.0f) - 1.0f; - out[i + 6] = (( (b >> 6 ) & 0x1) * 2.0f) - 1.0f; - out[i + 5] = (( (b >> 5 ) & 0x1) * 2.0f) - 1.0f; - out[i + 4] = (( (b >> 4 ) & 0x1) * 2.0f) - 1.0f; - out[i + 3] = (( (b >> 3 ) & 0x1) * 2.0f) - 1.0f; - out[i + 2] = (( (b >> 2 ) & 0x1) * 2.0f) - 1.0f; - out[i + 1] = (( (b >> 1 ) & 0x1) * 2.0f) - 1.0f; - out[i] = ((b & 0x1) * 2.0f) - 1.0f; - } + len = ax25_prepare_frame(d_ax25_tmp_buf, (uint8_t *) pmt::blob_data(pdu), + d_pdu_len, AX25_UI_FRAME, d_ax25_addr, + d_ax25_addr_len, 0x03, 1, 1, 1); + + status = ax25_bit_stuffing(d_ax25_pdu, &encoded_len, + d_ax25_tmp_buf, len, 1, 1); + if (status != AX25_ENC_OK) { + LOG_WARN("Failed to properly encode into AX.25 frame"); + return 0; } - inline void - upsat_fsk_frame_encoder_impl::add_sob (uint64_t item) - { - static const pmt::pmt_t sob_key = pmt::string_to_symbol ("tx_sob"); - static const pmt::pmt_t value = pmt::PMT_T; - static const pmt::pmt_t srcid = pmt::string_to_symbol (alias ()); - add_item_tag (0, item, sob_key, value, srcid); + /* Due to bit stuffing the resulting bit number may not be + * a multiple of 8. Thus we append proper number of zeros + * after the SYNC flag. So neither the AX.25 or the FSK + * framing are affected + */ + extra_bits = 8 - (encoded_len % 8); + encoded_len += extra_bits; + + /* + * Set the frame length at the corresponding field. + * NOTE: The frame length is calculated taking consideration only + * the address field (if exists) and the payload. Length and CRC fields + * are NOT included. + */ + len_field = (uint8_t)(encoded_len / 8); + + /* Apply whitening */ + if (d_whitening) { + d_scrambler.reset(); + d_scrambler.scramble(&len_field, &len_field, 1); + d_scrambler.scramble_one_bit_per_byte(d_ax25_pdu, d_ax25_pdu, + encoded_len); } - inline void - upsat_fsk_frame_encoder_impl::add_eob (uint64_t item) - { - static const pmt::pmt_t eob_key = pmt::string_to_symbol ("tx_eob"); - static const pmt::pmt_t value = pmt::PMT_T; - static const pmt::pmt_t srcid = pmt::string_to_symbol (alias ()); - add_item_tag (0, item, eob_key, value, srcid); + d_pdu[d_preamble_len + d_sync_word_len] = len_field; + + /* If it is necessary calculate and append the CRC */ + if (d_append_crc) { + LOG_WARN("AX.25 has its own CRC-16 field. Skipping..."); } - inline int - upsat_fsk_frame_encoder_impl::raw_frame_handling (float* out, - int noutput_items) - { - uint16_t crc; - size_t min_available; - pmt::pmt_t pdu; + d_pdu_len = d_preamble_len + d_sync_word_len + 1 + encoded_len / 8; - /* - * If the whole previous frame has been successfully sent, block waiting - * for a new one - */ - if (d_encoded == 0) { - pdu = delete_head_blocking (pmt::mp ("pdu")); - d_pdu_len = pmt::blob_length (pdu); + /* NRZ encoding the FSK preamble with the standard method */ + map_msb_first(d_pdu_encoded, (d_preamble_len + d_sync_word_len + 1) * 8); - if (d_pdu_len > UPSAT_MAX_FRAME_LEN) { - LOG_ERROR("PDU is greater than the supported. Dropping the PDU"); - return 0; - } - /* - * Set the frame length at the corresponding field. - * NOTE: The frame length is calculated taking consideration only - * the address field (if exists) and the payload. Length and CRC fields - * are NOT included. - */ - d_pdu[d_preamble_len + d_sync_word_len] = (uint8_t) d_pdu_len; - - /* Append the variable length PDU */ - memcpy (d_pdu + d_preamble_len + d_sync_word_len + 1, - pmt::blob_data (pdu), d_pdu_len); - - /* If it is necessary calculate and append the CRC */ - if (d_append_crc) { - crc = crc::crc16_ccitt (d_pdu + d_preamble_len + d_sync_word_len, - d_pdu_len + 1); - /* CRC must be transmitted MSB first */ - crc = htons (crc); - memcpy (d_pdu + d_preamble_len + d_sync_word_len + 1 + d_pdu_len, - &crc, sizeof(uint16_t)); - d_pdu_len += sizeof(uint16_t); - } - - /* - * Whitening is performed on all bytes except preamble and SYNC fields - */ - if (d_whitening) { - d_scrambler.reset (); - d_scrambler.scramble (d_pdu + d_preamble_len + d_sync_word_len, - d_pdu + d_preamble_len + d_sync_word_len, - d_pdu_len + 1); - } - - d_pdu_len += d_preamble_len + d_sync_word_len + 1; - - /* - * NRZ Encode the whole frame - */ - if (d_msb_first) { - map_msb_first (d_pdu_encoded, d_pdu_len * 8); - } - else { - map_lsb_first (d_pdu_encoded, d_pdu_len * 8); - } - - /* Reset the settling trailing samples */ - memset (d_pdu_encoded + d_pdu_len * 8, 0, - d_settling_samples * sizeof(float)); - - /* The new frame now has a bigger size of course*/ - d_pdu_len += d_settling_samples / 8; - - /* Start of burst */ - add_sob (nitems_written (0)); - } - - noutput_items = std::max (0, noutput_items); - min_available = std::min ((size_t) noutput_items, - (d_pdu_len - d_encoded) * 8); - - memcpy (out, d_pdu_encoded + d_encoded * 8, - min_available * sizeof(float)); - d_encoded += min_available / 8; - - /* End of the frame reached */ - if (d_encoded == d_pdu_len) { - add_eob (nitems_written (0) + min_available - 1); - d_encoded = 0; - } - - return min_available; + /* NRZ encode the AX.25 part of the FSK frame */ + for (i = 0; i < encoded_len - extra_bits; i++) { + d_pdu_encoded[i + (d_preamble_len + d_sync_word_len + 1) * 8] + = (d_ax25_pdu[i] * 2.0f) - 1.0f; } - inline int - upsat_fsk_frame_encoder_impl::ax25_frame_handling (float* out, - int noutput_items) - { - uint16_t crc; - size_t min_available; - pmt::pmt_t pdu; - size_t len; - size_t encoded_len; - ax25_encode_status_t status; - size_t extra_bits; - size_t i; - uint8_t len_field; + /* Reset the settling trailing samples */ + memset(&d_pdu_encoded[d_pdu_len * 8], 0, + d_settling_samples * sizeof(float)); - /* - * If the whole previous frame has been successfully sent, block waiting - * for a new one - */ - if (d_encoded == 0) { - /* Reset the buffer */ - memset(d_ax25_pdu, 0, 2 * d_max_pdu_len * 8); - memset(d_pdu_encoded, 0, d_max_pdu_len * 8 * sizeof(float)); - pdu = delete_head_blocking (pmt::mp ("pdu")); - d_pdu_len = pmt::blob_length (pdu); + /* The new frame now has a bigger size of course*/ + d_pdu_len += d_settling_samples / 8; - if (d_pdu_len > UPSAT_MAX_FRAME_LEN) { - LOG_ERROR("PDU is greater than the supported. Dropping the PDU"); - return 0; - } + /* Start of burst */ + add_sob(nitems_written(0)); + } - len = ax25_prepare_frame(d_ax25_tmp_buf, (uint8_t *) pmt::blob_data (pdu), - d_pdu_len, AX25_UI_FRAME, d_ax25_addr, - d_ax25_addr_len, 0x03, 1, 1, 1); + noutput_items = std::max(0, noutput_items); + min_available = std::min((size_t) noutput_items, + (d_pdu_len - d_encoded) * 8); - status = ax25_bit_stuffing(d_ax25_pdu, &encoded_len, - d_ax25_tmp_buf, len, 1, 1); - if(status != AX25_ENC_OK) { - LOG_WARN("Failed to properly encode into AX.25 frame"); - return 0; - } + memcpy(out, d_pdu_encoded + d_encoded * 8, + min_available * sizeof(float)); + d_encoded += min_available / 8; - /* Due to bit stuffing the resulting bit number may not be - * a multiple of 8. Thus we append proper number of zeros - * after the SYNC flag. So neither the AX.25 or the FSK - * framing are affected - */ - extra_bits = 8 - (encoded_len % 8); - encoded_len += extra_bits; + /* End of the frame reached */ + if (d_encoded == d_pdu_len) { + add_eob(nitems_written(0) + min_available - 1); + d_encoded = 0; + } - /* - * Set the frame length at the corresponding field. - * NOTE: The frame length is calculated taking consideration only - * the address field (if exists) and the payload. Length and CRC fields - * are NOT included. - */ - len_field = (uint8_t) (encoded_len/8); + return min_available; +} - /* Apply whitening */ - if (d_whitening) { - d_scrambler.reset (); - d_scrambler.scramble(&len_field, &len_field, 1); - d_scrambler.scramble_one_bit_per_byte (d_ax25_pdu, d_ax25_pdu, - encoded_len); - } +int +upsat_fsk_frame_encoder_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *out = (float *) output_items[0]; - d_pdu[d_preamble_len + d_sync_word_len] = len_field; + if (d_is_ax25) { + return ax25_frame_handling(out, noutput_items); + } + else { + return raw_frame_handling(out, noutput_items); + } +} - /* If it is necessary calculate and append the CRC */ - if (d_append_crc) { - LOG_WARN("AX.25 has its own CRC-16 field. Skipping..."); - } - - d_pdu_len = d_preamble_len + d_sync_word_len + 1 + encoded_len/8; - - /* NRZ encoding the FSK preamble with the standard method */ - map_msb_first (d_pdu_encoded, (d_preamble_len + d_sync_word_len + 1) * 8); - - /* NRZ encode the AX.25 part of the FSK frame */ - for(i = 0; i < encoded_len - extra_bits; i++){ - d_pdu_encoded[i + (d_preamble_len + d_sync_word_len + 1)*8] - = (d_ax25_pdu[i] * 2.0f) - 1.0f; - } - - /* Reset the settling trailing samples */ - memset (&d_pdu_encoded[d_pdu_len * 8], 0, - d_settling_samples * sizeof(float)); - - /* The new frame now has a bigger size of course*/ - d_pdu_len += d_settling_samples/8; - - /* Start of burst */ - add_sob (nitems_written (0)); - } - - noutput_items = std::max (0, noutput_items); - min_available = std::min ((size_t) noutput_items, - (d_pdu_len - d_encoded) * 8); - - memcpy (out, d_pdu_encoded + d_encoded * 8, - min_available * sizeof(float)); - d_encoded += min_available / 8; - - /* End of the frame reached */ - if (d_encoded == d_pdu_len) { - add_eob (nitems_written (0) + min_available - 1); - d_encoded = 0; - } - - return min_available; - } - - int - upsat_fsk_frame_encoder_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - float *out = (float *) output_items[0]; - - if(d_is_ax25) { - return ax25_frame_handling(out, noutput_items); - } - else{ - return raw_frame_handling(out, noutput_items); - } - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/upsat_fsk_frame_encoder_impl.h b/lib/upsat_fsk_frame_encoder_impl.h index 25cb8fa..6ec5551 100644 --- a/lib/upsat_fsk_frame_encoder_impl.h +++ b/lib/upsat_fsk_frame_encoder_impl.h @@ -25,70 +25,67 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class upsat_fsk_frame_encoder_impl : public upsat_fsk_frame_encoder - { - private: - const std::vector d_preamble; - const size_t d_preamble_len; - const std::vector d_sync_word; - const size_t d_sync_word_len; - const bool d_append_crc; - const bool d_whitening; - const bool d_manchester; - const bool d_msb_first; - const bool d_is_ax25; - const size_t d_max_pdu_len; - const size_t d_settling_samples; - size_t d_encoded; - size_t d_pdu_len; - whitening d_scrambler; - uint8_t *d_pdu; - uint8_t *d_ax25_pdu; - uint8_t *d_ax25_tmp_buf; - uint8_t *d_ax25_addr; - size_t d_ax25_addr_len; - float *d_pdu_encoded; +class upsat_fsk_frame_encoder_impl : public upsat_fsk_frame_encoder { +private: + const std::vector d_preamble; + const size_t d_preamble_len; + const std::vector d_sync_word; + const size_t d_sync_word_len; + const bool d_append_crc; + const bool d_whitening; + const bool d_manchester; + const bool d_msb_first; + const bool d_is_ax25; + const size_t d_max_pdu_len; + const size_t d_settling_samples; + size_t d_encoded; + size_t d_pdu_len; + whitening d_scrambler; + uint8_t *d_pdu; + uint8_t *d_ax25_pdu; + uint8_t *d_ax25_tmp_buf; + uint8_t *d_ax25_addr; + size_t d_ax25_addr_len; + float *d_pdu_encoded; - inline void - map_msb_first (float *out, size_t nsamples_out); - inline void - map_lsb_first (float *out, size_t nsamples_out); - inline void - add_sob (uint64_t item); - inline void - add_eob (uint64_t item); + inline void + map_msb_first(float *out, size_t nsamples_out); + inline void + map_lsb_first(float *out, size_t nsamples_out); + inline void + add_sob(uint64_t item); + inline void + add_eob(uint64_t item); - inline int - raw_frame_handling(float *out, int noutput_items); - inline int - ax25_frame_handling(float *out, int noutput_items); + inline int + raw_frame_handling(float *out, int noutput_items); + inline int + ax25_frame_handling(float *out, int noutput_items); - public: - upsat_fsk_frame_encoder_impl (const std::vector& preamble, - const std::vector& sync_word, - bool append_crc, bool whitening, - bool manchester, - bool msb_first, - bool ax25_format, - const std::string& ax25_dest_addr, - uint8_t ax25_dest_ssid, - const std::string& ax25_src_addr, - uint8_t ax25_src_ssid, - size_t settling_samples); - ~upsat_fsk_frame_encoder_impl (); +public: + upsat_fsk_frame_encoder_impl(const std::vector &preamble, + const std::vector &sync_word, + bool append_crc, bool whitening, + bool manchester, + bool msb_first, + bool ax25_format, + const std::string &ax25_dest_addr, + uint8_t ax25_dest_ssid, + const std::string &ax25_src_addr, + uint8_t ax25_src_ssid, + size_t settling_samples); + ~upsat_fsk_frame_encoder_impl(); - // Where all the action really happens - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + // Where all the action really happens + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_UPSAT_FSK_FRAME_ENCODER_IMPL_H */ diff --git a/lib/waterfall_sink_impl.cc b/lib/waterfall_sink_impl.cc index 94c1f30..bad35b3 100644 --- a/lib/waterfall_sink_impl.cc +++ b/lib/waterfall_sink_impl.cc @@ -25,244 +25,241 @@ #include #include "waterfall_sink_impl.h" #include -namespace gr +namespace gr { +namespace satnogs { + +waterfall_sink::sptr +waterfall_sink::make(double samp_rate, double center_freq, + double fps, size_t fft_size, + const std::string &filename, int mode) { - namespace satnogs - { - - waterfall_sink::sptr - waterfall_sink::make (double samp_rate, double center_freq, - double fps, size_t fft_size, - const std::string& filename, int mode) - { - return gnuradio::get_initial_sptr ( - new waterfall_sink_impl (samp_rate, center_freq, + return gnuradio::get_initial_sptr( + new waterfall_sink_impl(samp_rate, center_freq, fps, fft_size, filename, mode)); +} + +/* + * The private constructor + */ +waterfall_sink_impl::waterfall_sink_impl(double samp_rate, + double center_freq, + double pps, + size_t fft_size, + const std::string &filename, + int mode) : + gr::sync_block("waterfall_sink", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(0, 0, 0)), + d_samp_rate(samp_rate), + d_pps(pps), + d_fft_size(fft_size), + d_mode((wf_mode_t)mode), + d_refresh((d_samp_rate / fft_size) / pps), + d_fft_cnt(0), + d_fft_shift((size_t)(ceil(fft_size / 2.0))), + d_samples_cnt(0), + d_fft(fft_size) +{ + float r = 0.0; + const int alignment_multiple = volk_get_alignment() + / (fft_size * sizeof(gr_complex)); + set_alignment(std::max(1, alignment_multiple)); + set_output_multiple(fft_size); + + d_shift_buffer = (gr_complex *) volk_malloc( + fft_size * sizeof(gr_complex), volk_get_alignment()); + if (!d_shift_buffer) { + LOG_ERROR("Could not allocate aligned memory"); + throw std::runtime_error("Could not allocate aligned memory"); + } + + d_hold_buffer = (float *)volk_malloc(fft_size * sizeof(gr_complex), + volk_get_alignment()); + if (!d_hold_buffer) { + LOG_ERROR("Could not allocate aligned memory"); + throw std::runtime_error("Could not allocate aligned memory"); + } + memset(d_hold_buffer, 0, fft_size * sizeof(gr_complex)); + + d_tmp_buffer = (float *) volk_malloc(fft_size * sizeof(float), + volk_get_alignment()); + if (!d_tmp_buffer) { + LOG_ERROR("Could not allocate aligned memory"); + throw std::runtime_error("Could not allocate aligned memory"); + } + + d_fos.open(filename, std::ios::binary | std::ios::trunc); + + /* Append header for proper plotting */ + r = fft_size; + d_fos.write((char *)&r, sizeof(float)); + for (size_t i = 0; i < fft_size; i++) { + r = (samp_rate / fft_size * i) - samp_rate / 2.0 + center_freq; + d_fos.write((char *)&r, sizeof(float)); + } +} + +/* + * Our virtual destructor. + */ +waterfall_sink_impl::~waterfall_sink_impl() +{ + d_fos.close(); + volk_free(d_shift_buffer); + volk_free(d_hold_buffer); + volk_free(d_tmp_buffer); +} + +int +waterfall_sink_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + size_t n_fft = ((size_t) noutput_items / d_fft_size); + + switch (d_mode) { + case WATERFALL_MODE_DECIMATION: + compute_decimation(in, n_fft); + break; + case WATERFALL_MODE_MAX_HOLD: + compute_max_hold(in, n_fft); + break; + case WATERFALL_MODE_MEAN: + compute_mean(in, n_fft); + break; + default: + LOG_ERROR("Wrong waterfall mode"); + throw std::runtime_error("Wrong waterfall mode"); + return -1; + } + + return n_fft * d_fft_size; +} + +void +waterfall_sink_impl::compute_decimation(const gr_complex *in, size_t n_fft) +{ + size_t i; + float t; + gr_complex *fft_in; + for (i = 0; i < n_fft; i++) { + d_fft_cnt++; + if (d_fft_cnt > d_refresh) { + fft_in = d_fft.get_inbuf(); + memcpy(fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); + d_fft.execute(); + /* Perform FFT shift */ + memcpy(d_shift_buffer, &d_fft.get_outbuf()[d_fft_shift], + sizeof(gr_complex) * (d_fft_size - d_fft_shift)); + memcpy(&d_shift_buffer[d_fft_size - d_fft_shift], + &d_fft.get_outbuf()[0], sizeof(gr_complex) * d_fft_shift); + + /* Compute the energy in dB */ + volk_32fc_s32f_x2_power_spectral_density_32f(d_hold_buffer, + d_shift_buffer, + (float) d_fft_size, 1.0, + d_fft_size); + /* Write the result to the file */ + t = (float)(d_samples_cnt / d_samp_rate); + d_fos.write((char *) &t, sizeof(float)); + d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); + d_fft_cnt = 0; } + d_samples_cnt += d_fft_size; + } +} - /* - * The private constructor - */ - waterfall_sink_impl::waterfall_sink_impl (double samp_rate, - double center_freq, - double pps, - size_t fft_size, - const std::string& filename, - int mode) : - gr::sync_block ("waterfall_sink", - gr::io_signature::make (1, 1, sizeof(gr_complex)), - gr::io_signature::make (0, 0, 0)), - d_samp_rate (samp_rate), - d_pps (pps), - d_fft_size (fft_size), - d_mode ((wf_mode_t)mode), - d_refresh( (d_samp_rate / fft_size) / pps), - d_fft_cnt(0), - d_fft_shift((size_t)(ceil(fft_size/2.0))), - d_samples_cnt(0), - d_fft (fft_size) - { - float r = 0.0; - const int alignment_multiple = volk_get_alignment () - / (fft_size * sizeof(gr_complex)); - set_alignment (std::max (1, alignment_multiple)); - set_output_multiple (fft_size); +void +waterfall_sink_impl::compute_max_hold(const gr_complex *in, size_t n_fft) +{ + size_t i; + size_t j; + float t; + gr_complex *fft_in; + for (i = 0; i < n_fft; i++) { + fft_in = d_fft.get_inbuf(); + memcpy(fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); + d_fft.execute(); + /* Perform FFT shift */ + memcpy(d_shift_buffer, &d_fft.get_outbuf()[d_fft_shift], + sizeof(gr_complex) * (d_fft_size - d_fft_shift)); + memcpy(&d_shift_buffer[d_fft_size - d_fft_shift], + &d_fft.get_outbuf()[0], sizeof(gr_complex) * d_fft_shift); - d_shift_buffer = (gr_complex *) volk_malloc ( - fft_size * sizeof(gr_complex), volk_get_alignment()); - if(!d_shift_buffer){ - LOG_ERROR("Could not allocate aligned memory"); - throw std::runtime_error("Could not allocate aligned memory"); + /* Normalization factor */ + volk_32fc_s32fc_multiply_32fc(d_shift_buffer, d_shift_buffer, + 1.0 / d_fft_size, d_fft_size); + + /* Compute the mag^2 */ + volk_32fc_magnitude_squared_32f(d_tmp_buffer, d_shift_buffer, + d_fft_size); + /* Max hold */ + volk_32f_x2_max_32f(d_hold_buffer, d_hold_buffer, d_tmp_buffer, + d_fft_size); + d_fft_cnt++; + if (d_fft_cnt > d_refresh) { + /* Compute the energy in dB */ + for (j = 0; j < d_fft_size; j++) { + d_hold_buffer[j] = 10.0 * log10f(d_hold_buffer[j] + 1.0e-20); } - d_hold_buffer = (float *)volk_malloc(fft_size * sizeof(gr_complex), - volk_get_alignment()); - if(!d_hold_buffer){ - LOG_ERROR("Could not allocate aligned memory"); - throw std::runtime_error("Could not allocate aligned memory"); - } - memset(d_hold_buffer, 0, fft_size * sizeof(gr_complex)); + /* Write the result to the file */ + t = (float)(d_samples_cnt / d_samp_rate); + d_fos.write((char *) &t, sizeof(float)); + d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); - d_tmp_buffer = (float *) volk_malloc (fft_size * sizeof(float), - volk_get_alignment ()); - if (!d_tmp_buffer) { - LOG_ERROR("Could not allocate aligned memory"); - throw std::runtime_error ("Could not allocate aligned memory"); - } - - d_fos.open(filename, std::ios::binary | std::ios::trunc); - - /* Append header for proper plotting */ - r = fft_size; - d_fos.write((char *)&r, sizeof(float)); - for(size_t i = 0; i < fft_size; i++) { - r = (samp_rate/fft_size * i ) - samp_rate/2.0 + center_freq; - d_fos.write((char *)&r, sizeof(float)); - } + /* Reset */ + d_fft_cnt = 0; + memset(d_hold_buffer, 0, d_fft_size * sizeof(float)); } + d_samples_cnt += d_fft_size; + } +} - /* - * Our virtual destructor. - */ - waterfall_sink_impl::~waterfall_sink_impl () - { - d_fos.close(); - volk_free(d_shift_buffer); - volk_free(d_hold_buffer); - volk_free(d_tmp_buffer); +void +waterfall_sink_impl::compute_mean(const gr_complex *in, size_t n_fft) +{ + size_t i; + size_t j; + float t; + gr_complex *fft_in; + for (i = 0; i < n_fft; i++) { + fft_in = d_fft.get_inbuf(); + memcpy(fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); + d_fft.execute(); + /* Perform FFT shift */ + memcpy(d_shift_buffer, &d_fft.get_outbuf()[d_fft_shift], + sizeof(gr_complex) * (d_fft_size - d_fft_shift)); + memcpy(&d_shift_buffer[d_fft_size - d_fft_shift], + &d_fft.get_outbuf()[0], sizeof(gr_complex) * d_fft_shift); + + /* Accumulate the complex numbers */ + volk_32f_x2_add_32f(d_hold_buffer, d_hold_buffer, + (float *)d_shift_buffer, 2 * d_fft_size); + d_fft_cnt++; + if (d_fft_cnt > d_refresh) { + /* + * Compute the energy in dB performing the proper normalization + * before any dB calculation, emulating the mean + */ + volk_32fc_s32f_x2_power_spectral_density_32f( + d_hold_buffer, (gr_complex *)d_hold_buffer, + (float) d_fft_cnt * d_fft_size, 1.0, d_fft_size); + + /* Write the result to the file */ + t = (float)(d_samples_cnt / d_samp_rate); + d_fos.write((char *) &t, sizeof(float)); + d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); + + /* Reset */ + d_fft_cnt = 0; + memset(d_hold_buffer, 0, 2 * d_fft_size * sizeof(float)); } + d_samples_cnt += d_fft_size; + } +} - int - waterfall_sink_impl::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const gr_complex *in = (const gr_complex *) input_items[0]; - size_t n_fft = ((size_t) noutput_items / d_fft_size); - - switch (d_mode) - { - case WATERFALL_MODE_DECIMATION: - compute_decimation (in, n_fft); - break; - case WATERFALL_MODE_MAX_HOLD: - compute_max_hold (in, n_fft); - break; - case WATERFALL_MODE_MEAN: - compute_mean (in, n_fft); - break; - default: - LOG_ERROR("Wrong waterfall mode"); - throw std::runtime_error ("Wrong waterfall mode"); - return -1; - } - - return n_fft * d_fft_size; - } - - void - waterfall_sink_impl::compute_decimation (const gr_complex* in, size_t n_fft) - { - size_t i; - float t; - gr_complex *fft_in; - for(i = 0; i < n_fft; i++){ - d_fft_cnt++; - if(d_fft_cnt > d_refresh){ - fft_in = d_fft.get_inbuf(); - memcpy(fft_in, in + i*d_fft_size, d_fft_size*sizeof(gr_complex)); - d_fft.execute(); - /* Perform FFT shift */ - memcpy (d_shift_buffer, &d_fft.get_outbuf ()[d_fft_shift], - sizeof(gr_complex) * (d_fft_size - d_fft_shift)); - memcpy (&d_shift_buffer[d_fft_size - d_fft_shift], - &d_fft.get_outbuf ()[0], sizeof(gr_complex) * d_fft_shift); - - /* Compute the energy in dB */ - volk_32fc_s32f_x2_power_spectral_density_32f (d_hold_buffer, - d_shift_buffer, - (float) d_fft_size, 1.0, - d_fft_size); - /* Write the result to the file */ - t = (float)(d_samples_cnt / d_samp_rate); - d_fos.write((char *) &t, sizeof(float)); - d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); - d_fft_cnt = 0; - } - d_samples_cnt += d_fft_size; - } - } - - void - waterfall_sink_impl::compute_max_hold (const gr_complex* in, size_t n_fft) - { - size_t i; - size_t j; - float t; - gr_complex *fft_in; - for(i = 0; i < n_fft; i++){ - fft_in = d_fft.get_inbuf (); - memcpy (fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); - d_fft.execute (); - /* Perform FFT shift */ - memcpy (d_shift_buffer, &d_fft.get_outbuf ()[d_fft_shift], - sizeof(gr_complex) * (d_fft_size - d_fft_shift)); - memcpy (&d_shift_buffer[d_fft_size - d_fft_shift], - &d_fft.get_outbuf ()[0], sizeof(gr_complex) * d_fft_shift); - - /* Normalization factor */ - volk_32fc_s32fc_multiply_32fc(d_shift_buffer, d_shift_buffer, - 1.0/d_fft_size, d_fft_size); - - /* Compute the mag^2 */ - volk_32fc_magnitude_squared_32f(d_tmp_buffer, d_shift_buffer, - d_fft_size); - /* Max hold */ - volk_32f_x2_max_32f (d_hold_buffer, d_hold_buffer, d_tmp_buffer, - d_fft_size); - d_fft_cnt++; - if(d_fft_cnt > d_refresh) { - /* Compute the energy in dB */ - for(j = 0; j < d_fft_size; j++){ - d_hold_buffer[j] = 10.0 * log10f(d_hold_buffer[j] + 1.0e-20); - } - - /* Write the result to the file */ - t = (float)(d_samples_cnt / d_samp_rate); - d_fos.write((char *) &t, sizeof(float)); - d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); - - /* Reset */ - d_fft_cnt = 0; - memset(d_hold_buffer, 0, d_fft_size * sizeof(float)); - } - d_samples_cnt += d_fft_size; - } - } - - void - waterfall_sink_impl::compute_mean (const gr_complex* in, size_t n_fft) - { - size_t i; - size_t j; - float t; - gr_complex *fft_in; - for(i = 0; i < n_fft; i++){ - fft_in = d_fft.get_inbuf (); - memcpy (fft_in, in + i * d_fft_size, d_fft_size * sizeof(gr_complex)); - d_fft.execute (); - /* Perform FFT shift */ - memcpy (d_shift_buffer, &d_fft.get_outbuf ()[d_fft_shift], - sizeof(gr_complex) * (d_fft_size - d_fft_shift)); - memcpy (&d_shift_buffer[d_fft_size - d_fft_shift], - &d_fft.get_outbuf ()[0], sizeof(gr_complex) * d_fft_shift); - - /* Accumulate the complex numbers */ - volk_32f_x2_add_32f(d_hold_buffer, d_hold_buffer, - (float *)d_shift_buffer, 2 * d_fft_size); - d_fft_cnt++; - if(d_fft_cnt > d_refresh) { - /* - * Compute the energy in dB performing the proper normalization - * before any dB calculation, emulating the mean - */ - volk_32fc_s32f_x2_power_spectral_density_32f ( - d_hold_buffer, (gr_complex *)d_hold_buffer, - (float) d_fft_cnt * d_fft_size, 1.0, d_fft_size); - - /* Write the result to the file */ - t = (float)(d_samples_cnt / d_samp_rate); - d_fos.write((char *) &t, sizeof(float)); - d_fos.write((char *) d_hold_buffer, d_fft_size * sizeof(float)); - - /* Reset */ - d_fft_cnt = 0; - memset(d_hold_buffer, 0, 2 * d_fft_size * sizeof(float)); - } - d_samples_cnt += d_fft_size; - } - } - - } /* namespace satnogs */ +} /* namespace satnogs */ } /* namespace gr */ diff --git a/lib/waterfall_sink_impl.h b/lib/waterfall_sink_impl.h index cf80b44..f4bbd98 100644 --- a/lib/waterfall_sink_impl.h +++ b/lib/waterfall_sink_impl.h @@ -27,59 +27,56 @@ #include #include -namespace gr -{ - namespace satnogs - { +namespace gr { +namespace satnogs { - class waterfall_sink_impl : public waterfall_sink - { - private: - /** - * The different types of operation of the waterfall - */ - typedef enum { - WATERFALL_MODE_DECIMATION = 0,//!< WATERFALL_MODE_DECIMATION Performs just a decimation and computes the energy only - WATERFALL_MODE_MAX_HOLD = 1, //!< WATERFALL_MODE_MAX_HOLD compute the max hold energy of all the FFT snapshots between two consecutive pixel rows - WATERFALL_MODE_MEAN = 2 //!< WATERFALL_MODE_MEAN compute the mean energy of all the FFT snapshots between two consecutive pixel rows - } wf_mode_t; +class waterfall_sink_impl : public waterfall_sink { +private: + /** + * The different types of operation of the waterfall + */ + typedef enum { + WATERFALL_MODE_DECIMATION = 0,//!< WATERFALL_MODE_DECIMATION Performs just a decimation and computes the energy only + WATERFALL_MODE_MAX_HOLD = 1, //!< WATERFALL_MODE_MAX_HOLD compute the max hold energy of all the FFT snapshots between two consecutive pixel rows + WATERFALL_MODE_MEAN = 2 //!< WATERFALL_MODE_MEAN compute the mean energy of all the FFT snapshots between two consecutive pixel rows + } wf_mode_t; - const double d_samp_rate; - double d_pps; - const size_t d_fft_size; - wf_mode_t d_mode; - size_t d_refresh; - size_t d_fft_cnt; - size_t d_fft_shift; - size_t d_samples_cnt; - fft::fft_complex d_fft; - gr_complex *d_shift_buffer; - float *d_hold_buffer; - float *d_tmp_buffer; - std::ofstream d_fos; + const double d_samp_rate; + double d_pps; + const size_t d_fft_size; + wf_mode_t d_mode; + size_t d_refresh; + size_t d_fft_cnt; + size_t d_fft_shift; + size_t d_samples_cnt; + fft::fft_complex d_fft; + gr_complex *d_shift_buffer; + float *d_hold_buffer; + float *d_tmp_buffer; + std::ofstream d_fos; - public: - waterfall_sink_impl (double samp_rate, double center_freq, - double pps, size_t fft_size, - const std::string& filename, int mode); - ~waterfall_sink_impl (); +public: + waterfall_sink_impl(double samp_rate, double center_freq, + double pps, size_t fft_size, + const std::string &filename, int mode); + ~waterfall_sink_impl(); - int - work (int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + int + work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); - void - compute_decimation(const gr_complex *in, size_t n_fft); + void + compute_decimation(const gr_complex *in, size_t n_fft); - void - compute_max_hold(const gr_complex *in, size_t n_fft); + void + compute_max_hold(const gr_complex *in, size_t n_fft); - void - compute_mean(const gr_complex *in, size_t n_fft); - }; + void + compute_mean(const gr_complex *in, size_t n_fft); +}; - } // namespace satnogs +} // namespace satnogs } // namespace gr #endif /* INCLUDED_SATNOGS_WATERFALL_SINK_IMPL_H */ diff --git a/lib/whitening.cc b/lib/whitening.cc index 300df68..0685e1c 100644 --- a/lib/whitening.cc +++ b/lib/whitening.cc @@ -26,10 +26,8 @@ #include #include -namespace gr -{ -namespace satnogs -{ +namespace gr { +namespace satnogs { int whitening::base_unique_id = 1; @@ -42,7 +40,7 @@ int whitening::base_unique_id = 1; * number of memory stages. */ whitening::whitening_sptr -whitening::make (uint32_t mask, uint32_t seed, uint32_t order) +whitening::make(uint32_t mask, uint32_t seed, uint32_t order) { return whitening::whitening_sptr(new whitening(mask, seed, order)); } @@ -55,19 +53,19 @@ whitening::make (uint32_t mask, uint32_t seed, uint32_t order) * @param order the order of the shift register. This is equal to the * number of memory stages. */ -whitening::whitening (uint32_t mask, uint32_t seed, uint32_t order) : - d_lfsr (mask, seed, order), - d_id(0) +whitening::whitening(uint32_t mask, uint32_t seed, uint32_t order) : + d_lfsr(mask, seed, order), + d_id(0) { d_id = base_unique_id++; } -whitening::~whitening () +whitening::~whitening() { } int -whitening::unique_id () +whitening::unique_id() { return d_id; } @@ -77,9 +75,9 @@ whitening::unique_id () * the initial seed. */ void -whitening::reset () +whitening::reset() { - d_lfsr.reset (); + d_lfsr.reset(); } /** @@ -90,33 +88,33 @@ whitening::reset () * @param msb if set to true, the descrambler starts from the msb */ void -whitening::scramble (uint8_t* out, const uint8_t* in, size_t len, bool msb) +whitening::scramble(uint8_t *out, const uint8_t *in, size_t len, bool msb) { size_t i; uint8_t b; - if(msb) { + if (msb) { for (i = 0; i < len; i++) { - b = d_lfsr.next_bit () << 7; - b |= d_lfsr.next_bit () << 6; - b |= d_lfsr.next_bit () << 5; - b |= d_lfsr.next_bit () << 4; - b |= d_lfsr.next_bit () << 3; - b |= d_lfsr.next_bit () << 2; - b |= d_lfsr.next_bit () << 1; - b |= d_lfsr.next_bit (); + b = d_lfsr.next_bit() << 7; + b |= d_lfsr.next_bit() << 6; + b |= d_lfsr.next_bit() << 5; + b |= d_lfsr.next_bit() << 4; + b |= d_lfsr.next_bit() << 3; + b |= d_lfsr.next_bit() << 2; + b |= d_lfsr.next_bit() << 1; + b |= d_lfsr.next_bit(); out[i] = in[i] ^ b; } } - else{ + else { for (i = 0; i < len; i++) { - b = d_lfsr.next_bit (); - b |= d_lfsr.next_bit () << 1; - b |= d_lfsr.next_bit () << 2; - b |= d_lfsr.next_bit () << 3; - b |= d_lfsr.next_bit () << 4; - b |= d_lfsr.next_bit () << 5; - b |= d_lfsr.next_bit () << 6; - b |= d_lfsr.next_bit () << 7; + b = d_lfsr.next_bit(); + b |= d_lfsr.next_bit() << 1; + b |= d_lfsr.next_bit() << 2; + b |= d_lfsr.next_bit() << 3; + b |= d_lfsr.next_bit() << 4; + b |= d_lfsr.next_bit() << 5; + b |= d_lfsr.next_bit() << 6; + b |= d_lfsr.next_bit() << 7; out[i] = in[i] ^ b; } } @@ -130,10 +128,10 @@ whitening::scramble (uint8_t* out, const uint8_t* in, size_t len, bool msb) * @param msb if set to true, the descrambler starts from the msb */ void -whitening::descramble (uint8_t* out, const uint8_t* in, size_t len, - bool msb) +whitening::descramble(uint8_t *out, const uint8_t *in, size_t len, + bool msb) { - scramble (out, in, len, msb); + scramble(out, in, len, msb); } /** @@ -144,12 +142,12 @@ whitening::descramble (uint8_t* out, const uint8_t* in, size_t len, * @param bits_num the number of bits to be scrambled */ void -whitening::scramble_one_bit_per_byte (uint8_t* out, const uint8_t* in, - size_t bits_num) +whitening::scramble_one_bit_per_byte(uint8_t *out, const uint8_t *in, + size_t bits_num) { size_t i; for (i = 0; i < bits_num; i++) { - out[i] = in[i] ^ d_lfsr.next_bit (); + out[i] = in[i] ^ d_lfsr.next_bit(); } } @@ -161,10 +159,10 @@ whitening::scramble_one_bit_per_byte (uint8_t* out, const uint8_t* in, * @param bits_num the number of bits to be descrambled */ void -whitening::descramble_one_bit_per_byte (uint8_t* out, const uint8_t* in, - size_t bits_num) +whitening::descramble_one_bit_per_byte(uint8_t *out, const uint8_t *in, + size_t bits_num) { - scramble_one_bit_per_byte (out, in, bits_num); + scramble_one_bit_per_byte(out, in, bits_num); } } /* namespace satnogs */