/** * */ package com.perforce.p4java.impl.generic.client; import com.perforce.p4java.impl.mapbased.rpc.func.helper.StringHelper; import com.perforce.p4java.impl.mapbased.rpc.sys.RpcLineEndFilterOutputStream; import com.perforce.p4java.impl.mapbased.rpc.sys.RpcPerforceFileType; import java.util.Arrays; import java.util.Map; /** * Defines the various line ending mappings needed * for text files in the transfer between client and server.<p> * * Crucially important for Windows / Mac / Linux / Nintendo * (etc.) text files; explanations are given elsewhere... */ public enum ClientLineEnding { FST_L_LOCAL, // LineTypeLocal FST_L_LF, // LineTypeRaw FST_L_CR, // LineTypeCr FST_L_CRLF, // LineTypeCrLf FST_L_LFCRLF; // LineTypeLfcrlf /** * The key for the system-wide line separator. */ public static final String LINESEP_PROPS_KEY = "line.separator"; /** * The local line end string, as retrieved from the system * properties. The JVM apparently guarantees that this is * accurate.... */ public static final String localLineEndStr = System.getProperty(LINESEP_PROPS_KEY, "\n"); /** * What the Perforce server uses internally to signal line end. * Not coincidentally, the same as the Unix, Linux, and Mac OS X * line end byte. */ public static final byte PERFORCE_SERVER_LINE_END_BYTE = '\n'; public static final byte[] FST_L_LOCAL_BYTES = localLineEndStr.getBytes(); public static final char FST_L_LF_CHAR = '\n'; public static final char FST_L_CR_CHAR = '\r'; public static final byte[] FST_L_LF_BYTES = new byte[] {'\n'}; public static final byte[] FST_L_CR_BYTES = new byte[] {'\r'}; public static final byte[] FST_L_CRLF_BYTES = new byte[] {'\r', '\n'}; public static final byte[] FST_L_LFCRLF_BYTES = new byte[] {'\n', '\r', '\n'}; // ?? - HR public static final boolean CONVERT_TEXT = !Arrays.equals(FST_L_LOCAL_BYTES, FST_L_LF_BYTES); /** * Decode the file's actual or intended line ending type from the passed-in * string. The line ending stuff is usually the second char (if it exists), * but that may be overridden if the associated file type is a raw text * type (usually something to do with merges or diff / resolve, apparently), * in which case we return FST_L_LF.<p> * * Hence the anomalous-looking second parameter here.... */ public static ClientLineEnding decodeFromServerString(String str, RpcPerforceFileType fileType) { if ((fileType != null) && (fileType == RpcPerforceFileType.FST_RTEXT)) { return FST_L_LF; // See comments above... this overrides everything } if (str == null) { return FST_L_LOCAL; } // Copied wholesale from the C++ API... // fileType [ lineType [ uncompress ] ] int tl = 0; if (str.length() >= 2) { tl = StringHelper.hexcharToInt(str.charAt(1)); } switch (tl) { case 0x1: return FST_L_LF; case 0x2: return FST_L_CR; case 0x3: return FST_L_CRLF; case 0x4: return FST_L_LFCRLF; default: return FST_L_LOCAL; } } /** * Determine whether we really need to translate newlines. Since the * server stores them internally as "\n" characters, we only need to * translate on systems where that's not the default -- currently * win and mac, but we use the system prop just to be sure... */ public static boolean needsLineEndFiltering(ClientLineEnding lineEndSpec) { if (lineEndSpec != null) { switch (lineEndSpec) { case FST_L_LOCAL: if (!localLineEndStr.equals( RpcLineEndFilterOutputStream.P4SERVER_LINSEP_STR)) { return true; } break; case FST_L_LF: break; case FST_L_CR: case FST_L_CRLF: case FST_L_LFCRLF: return true; } } return false; } /** * Return the byte array corresponding to the client line ending. * The default is {@link #FST_L_LOCAL_BYTES}. */ public static byte[] getLineEndBytes(ClientLineEnding lineEndSpec) { if (lineEndSpec != null) { switch (lineEndSpec) { case FST_L_LOCAL: return FST_L_LOCAL_BYTES; case FST_L_LF: return FST_L_LF_BYTES; case FST_L_CR: return FST_L_CR_BYTES; case FST_L_CRLF: return FST_L_CRLF_BYTES; case FST_L_LFCRLF: return FST_L_LFCRLF_BYTES; } } return FST_L_LOCAL_BYTES; } /** * Convert the line endings for any string found in the map to the * {@link #FST_L_LF_BYTES} values from {@link #localLineEndStr}. The * conversion will be done in place. * * @param map */ public static void convertMap(Map<String, Object> map) { if (map != null) { String convertTo = new String(FST_L_LF_BYTES); for (Map.Entry<String, Object> entry : map.entrySet()) { if (entry.getValue() instanceof String) { String value = ((String) entry.getValue()).replace(localLineEndStr, convertTo); map.put(entry.getKey(), value); } } } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 19903 | stuartrowe |
Branching //guest/perforce_software/p4java/... to //guest/stuartrowe/p4java/... |
||
//guest/perforce_software/p4java/r14.1/src/main/java/com/perforce/p4java/impl/generic/client/ClientLineEnding.java | |||||
#1 | 12541 | Matt Attaway | Initial add of the 14.1 p4java source code |