Riproduzione continua di byte in eccesso (COBS)


10

Sono sorpreso che questo non sia mai stato pubblicato prima!

L' algoritmo COBS ( Consistent Overhead Byte Stuffing ) viene utilizzato per delimitare i flussi di byte.

Scegliamo un marker di frame (useremo 0x00) e ogni volta che si verifica 0x00 nel flusso, questo viene sostituito con il numero di byte fino a quando si verifica il successivo 0x00 (lo chiameremo una pietra miliare). Ciò riduce l'intervallo di valori da 0..255 a 1..255, consentendo a 0x00 di delimitare in modo inequivocabile i frame nel flusso.
A un traguardo, se il prossimo 255B non contiene 0x00, questo supera la lunghezza massima del traguardo: l'algoritmo deve "bloccarsi" a 255B e inserire un altro traguardo. Questo è il "sovraccarico coerente".
Il primo byte sarà il primo traguardo, il traguardo finale sarà il numero di byte fino al marker del frame.

Alcuni esempi da Wikipedia (meglio leggere l'articolo in cui sono colorati):

0x00 as frame marker

Unencoded data (hex)    Encoded with COBS (hex)
00                      01 01 00
00 00                   01 01 01 00
11 22 00 33             03 11 22 02 33 00
11 22 33 44             05 11 22 33 44 00
11 00 00 00             02 11 01 01 01 00
01 02 03 ... FD FE      FF 01 02 03 ... FD FE 00
00 01 02 ... FC FD FE   01 FF 01 02 ... FC FD FE 00
01 02 03 ... FD FE FF   FF 01 02 03 ... FD FE 02 FF 00
02 03 04 ... FE FF 00   FF 02 03 04 ... FE FF 01 01 00
03 04 05 ... FF 00 01   FE 03 04 05 ... FF 02 01 00

Sfida: implementare questo nel programma più breve.

  • L'input è un flusso / array di byte non codificato, l'output è un flusso / array di byte codificato
  • Utilizzare qualsiasi tipo di input / output standard binario
  • Il marker finale del frame non è necessario
  • Il programma può restituire un array sovradimensionato
  • Un flusso che termina con 254 byte diversi da zero non richiede il trascinamento 0x00

Appunti

  • La lunghezza di ritorno nel caso peggiore è numBytes + (numBytes / 254) + 1

Esempio

Abbiamo l'array di byte

[0] 0x01
[1] 0x02
[2] 0x00
[3] 0x03
[4] 0x04
[5] 0x05
[6] 0x00
[7] 0x06

Per ognuno di 0x00noi dobbiamo indicare (in una pietra miliare) dove 0x00sarebbe stato il prossimo .

[0] 0x03   #Milestone. Refers to the original [2] - "The next 0x00 is in 3B"
[1] 0x01   #Original [0]
[2] 0x02   #Original [1]
[3] 0x04   #Milestone. Refers to the original [6] - "The next 0x00 is in 4B"
[4] 0x03   #
[5] 0x04   #
[6] 0x05   # Originals [3..5]
[7] 0x02   #Milestone. Refers to the end frame marker
[8] 0x06   #Original [7]
[9] 0x00   #Optional. End frame marker.

3
Probabilmente dovresti includerlo nelle specifiche: come eccezione speciale, se un pacchetto termina con un gruppo di 254 byte diversi da zero, non è necessario aggiungere il byte zero finale. Ciò consente di risparmiare un byte in alcune situazioni. (citando Wikipedia)
Arnauld

3
@LuisMendo Concordato. Ora che ho esaminato tutti i casi di test, posso confermare che questo è un po 'sottodimensionato.
Arnauld,

@Arnauld, ho dichiarato che il creatore del telaio non è necessario comunque :)
Patrick

Nell'esempio, il primo byte di output dovrebbe essere 0x03, non 0x02, a meno che non mi sbagli ...
Olivier Grégoire

1
@Arnauld per quanto riguarda il caso speciale di fine con 254 byte diversi da zero: d'accordo, e questo è un problema separato per il marker di frame finale. È per questo che il sesto esempio non ha un trailing 01ma ci sono due 01s nel nono (dove ci sono 254 byte diversi da zero seguiti da uno zero).
Nick Kennedy,

Risposte:




1

Python 2 , 125 byte

def f(a):
 r=[[]]
 for v in a:r+=[[]]*((len(r[-1])>253)+(v<1));r[-1]+=[v]*(v>0)
 return sum([[len(x)+1]+x for x in r],[])+[0]

Provalo online!


1

Gelatina , 27 byte

Oµ=0ks€254Ẏḟ€0L‘;Ɗ€F;Ṫ¬x`ƊỌ

Provalo online!

Un collegamento monadico che accetta come input un array di byte non codificato e restituisce l'array di byte codificato. Secondo le regole, il marker di frame finale viene omesso.

Spiegazione

Oµ                          | Convert to integer and start a new monadic chain
  =0k                       | Split after zeros
     s€254                  | Split each list into length 254 lists
          Ẏ                 | Tighten (reduce list depth by 1)
           ḟ€0              | Filter zeros out from each list
              L‘;Ɗ€         | Prepend the list length plus one to each list
                   F        | Flatten
                    ;Ṫ¬x`Ɗ  | Append an additional 1 if the original list ended with zero
                          Ọ | Convert back to bytes


0

J , 103 caratteri

Notare che il risultato dell'ultimo test case è diverso da wiki e altre lingue. Ciò è dovuto a questo puntatore al 254 ° zero byte al limite. Le cose diventano molto più facili, se questo non viene trattato come un caso speciale.

f =: 3 : 0
  k =. I. (y,0)=0
  s =. - 2 (-/) \ k
  (>: y i. 0), s (}:k) } y
 )

 f2 =: 3 : 0
   f each _254 <\ y
 )

Provalo online


Puoi prenderlo di 1 byte rimuovendo lo spazio finale alla fine dell'ultima riga.
ouflak,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.