136 lines
4.0 KiB
Java
136 lines
4.0 KiB
Java
package redis.clients.jedis;
|
|
|
|
import redis.clients.util.RedisInputStream;
|
|
import redis.clients.util.RedisOutputStream;
|
|
|
|
import java.io.*;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
public final class Protocol {
|
|
|
|
public static final int DEFAULT_PORT = 6379;
|
|
|
|
public static final byte DOLLAR_BYTE = '$';
|
|
public static final byte ASTERISK_BYTE = '*';
|
|
public static final byte PLUS_BYTE = '+';
|
|
public static final byte MINUS_BYTE = '-';
|
|
public static final byte COLON_BYTE = ':';
|
|
|
|
public void sendCommand(final RedisOutputStream os, final String name, final String... args) {
|
|
try {
|
|
os.write(ASTERISK_BYTE);
|
|
os.writeIntCrLf(args.length + 1);
|
|
os.write(DOLLAR_BYTE);
|
|
os.writeIntCrLf(name.length());
|
|
os.writeAsciiCrLf(name);
|
|
|
|
for (String str : args) {
|
|
os.write(DOLLAR_BYTE);
|
|
final int size = RedisOutputStream.utf8Length(str);
|
|
os.writeIntCrLf(size);
|
|
if (size == str.length())
|
|
os.writeAsciiCrLf(str);
|
|
else {
|
|
os.writeUtf8CrLf(str);
|
|
}
|
|
}
|
|
os.flush();
|
|
} catch (IOException e) {
|
|
throw new JedisException(e);
|
|
}
|
|
}
|
|
|
|
public void sendCommand(final RedisOutputStream os, final String name, final byte[]... args) {
|
|
try {
|
|
os.write(ASTERISK_BYTE);
|
|
os.writeIntCrLf(args.length + 1);
|
|
os.write(DOLLAR_BYTE);
|
|
os.writeIntCrLf(name.length());
|
|
os.writeAsciiCrLf(name);
|
|
|
|
for (final byte[] arg : args) {
|
|
os.write(DOLLAR_BYTE);
|
|
os.writeIntCrLf(arg.length);
|
|
os.write(arg);
|
|
os.writeCrLf();
|
|
}
|
|
os.flush();
|
|
} catch (IOException e) {
|
|
throw new JedisException(e);
|
|
}
|
|
}
|
|
|
|
private void processError(final RedisInputStream is) {
|
|
String message = is.readLine();
|
|
throw new JedisException(message);
|
|
}
|
|
|
|
private Object process(final RedisInputStream is) {
|
|
try {
|
|
byte b = is.readByte();
|
|
if (b == MINUS_BYTE) {
|
|
processError(is);
|
|
} else if (b == ASTERISK_BYTE) {
|
|
return processMultiBulkReply(is);
|
|
} else if (b == COLON_BYTE) {
|
|
return processInteger(is);
|
|
} else if (b == DOLLAR_BYTE) {
|
|
return processBulkReply(is);
|
|
} else if (b == PLUS_BYTE) {
|
|
return processStatusCodeReply(is);
|
|
} else {
|
|
throw new JedisException("Unknown reply: " + (char) b);
|
|
}
|
|
} catch (IOException e) {
|
|
throw new JedisException(e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private String processStatusCodeReply(final RedisInputStream is) {
|
|
return is.readLine();
|
|
}
|
|
|
|
private byte[] processBulkReply(final RedisInputStream is) {
|
|
int len = Integer.parseInt(is.readLine());
|
|
if (len == -1) {
|
|
return null;
|
|
}
|
|
byte[] read = new byte[len];
|
|
int offset = 0;
|
|
try {
|
|
while (offset < len) {
|
|
offset += is.read(read, offset, (len - offset));
|
|
}
|
|
// read 2 more bytes for the command delimiter
|
|
is.readByte();
|
|
is.readByte();
|
|
} catch (IOException e) {
|
|
throw new JedisException(e);
|
|
}
|
|
|
|
return read;
|
|
}
|
|
|
|
private Integer processInteger(final RedisInputStream is) {
|
|
String num = is.readLine();
|
|
return Integer.valueOf(num);
|
|
}
|
|
|
|
private List<Object> processMultiBulkReply(final RedisInputStream is) {
|
|
int num = Integer.parseInt(is.readLine());
|
|
if (num == -1) {
|
|
return null;
|
|
}
|
|
List<Object> ret = new ArrayList<Object>(num);
|
|
for (int i = 0; i < num; i++) {
|
|
ret.add(process(is));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public Object read(final RedisInputStream is) {
|
|
return process(is);
|
|
}
|
|
} |