g | x | w | all
Bytes Lang Time Link
071Python 3250408T004145ZCrSb0001
009Japt240829T115224ZShaggy
022x86240907T003125Zqwr
042APL+WIN240905T161648ZGraham
431Minecraft Function240902T031306ZLostXOR
077F#240831T012959ZJuuz
044C240830T092711Zjpa
017Jelly240829T223018ZUnrelate
126Python240829T140028ZTheLittl
089Go240829T144920Zbigyihsu
211205AB1E240829T103540ZKevin Cr
034JavaScript ES6240828T181212ZArnauld
015Uiua240828T194612Znyxbird

Python 3, 76 71 bytes

-5 bytes thanks to @ceilingcat

def r(v):
 t=s=0
 for b in v:t|=b&128<<s;s+=7
 return t-(t>>31>0)*2**32

Attempt This Online!

Takes input as a list of (hexadecimal) bytes. This is actually the same exact length as my solution for parsing Minecraft's VarLongInt, as we only need to change (t>2**31-1)*2**32 in the last line to (t>2**63-1)*2**64.

Japt, 10 9 bytes

Adheres to the OP's original, albeit severely lacking, spec which didn't require support for outputting negative values.

Takes input as a 2D-array of binary digits.

óv ÎÔc ì2

Try it (Includes all test cases)

23 21 bytes

This version does include support for negative outputs. Will try to golf it further if it's confirmed we actually need to support them.

óv ÎÔc ì2
¨2pHÉ
-VÑpH

Try it

x86, 24 23 22 bytes

Couldn't figure out any tricks to get rid of shift, so it's a straight-forward do-while loop, checking the byte's sign bit. Input in esi, output in ebx, everything clobbered.

-1 byte by using eax for the t calculations, so I can do 2-byte and al, imm8.

-1 byte by using lodsb instead of mov/inc (but I have to clear upper bits of eax).

parse:                          ; esi input pointer
  31 DB     xor     ebx, ebx    ; ebx result = 0
  31 C9     xor     ecx, ecx    ; ecx shift = 0
.loop:  
  AC        lodsb               ; al byte = [esi++]
  88 C2     mov     dl, al      ; save byte for test later
  83 E0 7F  and     eax, 0x7F   ; t &= 0x7F, clear upper bits
  D3 E0     sal     eax, cl     ; t <<= shift
  09 C3     or      ebx, eax    ; result |= t
  80 C1 07  add     cl, 7       ; shift += 7
  84 D2     test    dl, dl    
  78 EF     js      .loop       ; loop if byte's sign bit is set
  C3        ret                 ; return in ebx   

I formatted all above manually from a NASM listing. Please tell me if there's an easier way.

APL+WIN, 42 bytes

Prompts for bytes as a nested vector.

((-2*32)×↑i)+2⊥i←¯32↑∊⌽(×\¯1↓1,↑¨b)/1↓¨b←⎕

Try it online! Thanks to Dyalog Classic

Minecraft Function, 431 bytes

scoreboard objectives add a dummy
scoreboard players set c a 128
execute unless score a a < m a run scoreboard players set m a 1
execute store result score a a run data get storage x x[0]
data remove storage x x[0]
execute if score a a >= c a run schedule function p:f 1 
scoreboard players operation a a %= c a
scoreboard players operation a a *= m a
scoreboard players operation v a += a a
scoreboard players operation m a *= c a

This question wouldn't be complete without a Minecraft solution.

Run as a function named f in a data pack named p. Input is given as a list of bytes in array x of storage x, and can be set like so:

/data modify storage x x set value [221,199,1,71]

Output is given as the scoreboard value for player v of objective a, and can be viewed with:

/scoreboard players get v a

The function first sets up a scoreboard for holding variables, sets c = 128 and m = 1, then iterates over each byte a, performing these operations:

This builds up the value 7 bits at a time. The function terminates one iteration after it finds an a less than c (equivalent to not having its high bit set). Minecraft stores scoreboard values as 32 bit signed integers, so they roll over appropriately for negative numbers.

F#, 77 bytes

let rec p s (x::r)=x&&&127y|>int<<<s|||if-128y&&&x=0y then 0 else p(s+7)r
p 0

Try it online!

A function expression that takes input as a list of signed bytes and outputs a 64-bit signed int.

Commented

let rec p s (x :: r) = // recursive function p that takes the bit shift amount
                       // and deconstructs a byte list to the first byte x and the tail r
  x &&& 127y |> int    // convert the current byte's end to a signed int
  <<< s                // and shift it by s
  ||| if -128y &&& x = 0y then 0 // OR the value with 0 if the first bit is 0
      else p (s + 7) r           // otherwise repeat this process for the tail
p 0                    // apply the initial shift level to the full function

C, 44 bytes

p(char*x){return*x&127|(*x>>7?p(x+1)<<7:0);}

Attempt This Online!

Input is a char array, decoded recursively and returned as platform native int type. Negative values work correctly on platforms where int is 32 bits (which includes most current platforms such as ARM and x86_64).

Jelly, 17 bytes

ḣṪ€i0ƊFUḄNæ%Ø%H¤N

Try it online!

Input as a list of bit lists, LSB first.

ḣ  i Ɗ               Remove all elements after the first element which
 Ṫ€                  has a last element (MSB)
   i0                equal to 0,
 Ṫ€                  and remove every element's last element.
      F              Flatten,
       U             reverse,
        Ḅ            convert from binary.
         N      N    Under negation,
          æ%         "symmetric modulo"
            Ø%       2^32
              H¤     divided by 2.

"Symmetric modulo 2y" maps into the half-open interval (-y, y] for positive y (and behaving somewhat strangely for negative y). Unfortunately, this interval is open on the wrong end for two's complement representation, so this is corrected by flanking it with Negates.

Python, 143 137 135 126 bytes

lambda x,s=-7,r=0,c=0:(lambda y:y-(y>2147483647)*4294967296)(sum((r|(b&127)<<(s:=s+7)+0*(c:=b<128))if not c else 0for b in x))

Attempt This Online!

(-6 bytes thanks to @Kevin Cruijssen)

(-2 bytes thanks to @Jordan)

(-9 bytes after I realized I could refactor how lambda y worked, inspired by @Kevin Cruijssen's changing hex to dec)

First time trying code golf. Maybe I shouldn't have chosen parsing bits my first golf ¯\_(ツ)_/¯

Go, 89 bytes

func(B[]byte)(o int32){for i,b:=range B{o+=int32(b&127)<<(i*7)
if b&128<1{break}}
return}

Attempt This Online!

Input is a byte slice, and outputs a 32-bit integer.

05AB1E, 21 (or 12) bytes

η.Δθн_}€¦RJCDžI&ĀžJ*-

Input as a list of binary-strings (e.g. example 0xdd,0xc7,0x01,0x47. is input as ["11011101","11000111","00000001","01000111"])

Try it online or verify all test cases.

Explanation:

Step 1: Main part of the challenge:

η          # Get the prefixes of the (implicit) input-list
 .Δ        # Find the first prefix that's truthy for:
   θ       #  Pop and leave the last string of the current prefix
    н      #  Pop and leave its first bit
     _     #  Check that it's 0
  }€       # After the find_first: map over each prefix:
    ¦      #  Remove its first bit
     R     # Reverse this list of prefixes
      J    # Join them together
       C   # Convert it from a binary-string to a base-10 integer

Try just step 1 online for all test cases.

Step 2: Convert the unsigned to signed 32-bit integers:

D          # Duplicate the current value
   &       # Bitwise-AND it with
 žI        # constant value 2147483648
    Ā      # Check whether this is NOT 0
       *   # Multiply this 0 or 1 by
     žJ    # constant value 4294967296
        -  # Subtract that from the value of step 1
           # (after which the result is output implicitly)

JavaScript (ES6),  35  34 bytes

f=([v,...a])=>v&&v^(v&=128)|v*f(a)

Try it online!

Commented

f = (      // f is a recursive function taking:
  [ v,     //   v   = next byte from input array
    ...a ] //   a[] = remaining bytes
) =>       //
v          // stop if v is zero or undefined
&&         // otherwise, get the 7 least significant bits of v
v ^        // by XOR'ing v ...
(v &= 128) // ... with its MSB
           // and update v to its MSB
|          // merge this with ...
v *        // ... v (which is now 0x00 or 0x80) multiplied by
f(a)       // the result of a recursive call

Uiua, 15 bytes

°⋯♭▽≤⊗0:°⊏≡⍜⇌°⊂

Takes input as an array of 8-bit bytes (lsb-first)

Try it!

°⋯♭▽≤⊗0:°⊏≡⍜⇌°⊂
          ≡⍜⇌°⊂ # pull the msb from each row
       :°⊏      # range by the length under the msbs
     ⊗0         # find the first 0
   ▽≤           # keep the rows <= to its location
°⋯♭             # flatten and convert from binary