MultiInt snippertje
Met dit snippertje heb je de mogelijkheid om meerdere getallen in 1 getal-variable op te slaan. Zo kan je bijvoorbeeld 32 booleans in 1 getal opslaan. Wanneer je meerdere getallen wilt opslaan als 1 getal: Als 1e argument moet je de getallen meegeven in een array. Als 2e argument moet je een array meegeven die dient als "layout". Wanneer je dat getal weer wilt "uitpakken" tot een array met getallen: Als 1e argument moet je het getal meegeven. Als 2e argument moet je een array meegeven die dient als "layout". Zorg ervoor dat de layout bij zowel inpakken als uitpakken hetzelfde is, anders kunnen er vage dingen gebeuren. Houdt er ook rekening mee dat je niet meer dan 32 bits aan data in 1 getal kan opslaan. (jammer nou) De layout array (2e argument) kan zowel een numerieke als een assoc array zijn, zolang de "keys" maar overeen komen met het 1e argument bij inpakken. Gebruik: (voorbeeld) Mijn gebrekkig-engelse omschrijving staat in de code. ... ... Ja betere uitleg kan ik niet geven :P test em eens voor de lol :P ... Voordat de vraag komt: het nut hiervan: -sla 8 booleans op in 1 byte. (de int als output in de functie ord(); gooien en je hebt 1 teken) -sla 32 booleans op in 1 INT. -sla 2 booleans en 1 getal die nooit hoger wordt dan 63 op in 1 byte. "WTF MAN?! waarom zou je dat willen???" Ik heb dit systeem voornamelijk gemaakt om zoveel mogelijk data in een BASE64 encoding te proppen. Zo kan ik 6 booleans kwijt in 1 BASE64 teken. Handig om mee te zenden in een URL of op te slaan op iets waar alleen maar tekst toegestaan is. Uiteraard moet je het getal wel eerst omzetten naar BASE64 of een bytes-stream. Zie je het al voor je? 6 booleans (waar/niet waar) mee kunnen sturen in 1 teken van een URL? mooi hè... :P Enkele nootjes: -De functie houdt echt niet van negatieve getallen. Negatieve getallen worden afgerond naar 0. -De functie rond automatisch getallen af naar beneden wanneer deze te groot zijn voor zn toegewezen ruimte. -Het bereik van een variable is te berekenen: van 0 tot 2^TOEGEWEZEN_BITS - 1 Voorbeeldje van het opslaan van 4 booleans in 1 getal: Hint: http://www.phphulp.nl/php/scripts/11/1569/ Die werkt er wel handig mee: 6 booleans opslaan in 1 base64 teken die je veilig kan opslaan in text of url's.
[code]<?php/*
Function to store multiple integers in a single integer.
INPUT:
$target: MIXED representing an INT or an ARRAY.
When an INT is given, it will be extracted to multiple ints. OUTPUT will be an ARRAY containing the integers.
When an ARRAY is given, it will be stored to a single int. OUTPUT will be an INT.
$layout: ARRAY containing multiple integers representing the reserved amount of bits per integer.
OUTPUT:
MIXED: ARRAY or INT.
NOTES:
-You cannot store more then 32 bits of data.
Please don't try it: something unknown will happen. Seriously, i don't know what will happen.
This is what PHP.net says about shifting more than 32 bits of data: ( http://nl2.php.net/language.operators.bitwise )
"Warning: Don't right shift for more than 32 bits on 32 bits systems. Don't left shift in case it results to number longer than 32 bits."
So don't try it: it may blow up your CPU! if you CANNOT resist to try it: Try at your own risk! Remember to wear safetly glasses in case the CPU explodes in your face.
-If you store 32 bits of data, the integer may be a negative. Storing 31 bits or less should result in a positive integer.
-If an INT is out of range, it will be rounded to the highest possible value. Negative numbers will rounded to 0.
Examples:
$int = multiint( array(3,1), array(2,1)); //$int = 7; (binary 111)
$multi = multiint( $int , array(2,1)); //$multi = array(2,1);
$int = multiint( array(28,3), array(5,3)); //$int = 115; (binary 11100011)
$multi = multiint( $int , array(2,2,2,2)); //$multi = array(3,2,0,3);
$user_info = array(
'age' => 44,
'registered' => 1,
'status' => 7,
);
$user_info_layout = array(
'age' => 7, //range: 0-127 ( 2^7-1 = 127)
'registered' => 1, //range: 0 or 1 ( 2^1-1 = 1)
'status' => 3, //range: 0-7 ( 2^3-1 = 8)
);
$dataInt = multiint( $user_info , $user_info_layout); //$dataInt = 719 (binair: 1011001111)
$user_info2 = multiint( $dataInt , $user_info_layout); //$user_info2 = array('age' => 44,'registered' => 1,'status' => 7);
echo $user_info2['age'];//will output "44".
*/
function multiint($target,$layout) {
if(is_array($target)) {
$output = 0;
foreach($target as $key=>$int) {
$inv = min((1<<$layout[$key])-1,max(0,(int)$int));
$int = 0;
for($x=0;$x<$layout[$key];$x++) {
$int = ($int<<1) + ($inv&1);
$inv = $inv >> 1;
}
for($x=0;$x<$layout[$key];$x++) {
$output = ($output<<1) + ($int&1);
$int = $int >> 1;
}
}
return $output;
} else {
$target = (int)$target;
$output = array();
$layout = array_reverse($layout,true);
foreach($layout as $key=>$itemlength) {
$inv = 0;
$output[$key] = 0;
for($x=0;$x<$itemlength;$x++) {
$inv = ($inv<<1) + ($target&1);
$target = $target >> 1;
}
for($x=0;$x<$itemlength;$x++) {
$output[$key] = ($output[$key]<<1) + ($inv&1);
$inv = $inv >> 1;
}
}
$output = array_reverse($output,true);
return $output;
}
}
?>[/code]
Reacties
0