-/*
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
* limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
-
- Change History (most recent first):
-
-$Log: TXTRecord.java,v $
-Revision 1.2 2004/04/30 21:48:27 rpantos
-Change line endings for CVS.
-
-Revision 1.1 2004/04/30 16:29:35 rpantos
-First checked in.
To do:
- implement remove()
/**
Object used to construct and parse DNS-SD format TXT records.
- For more info see <a href="http://www.zeroconf.org/Rendezvous/txtrecords.html">DNS-SD TXT record format</a>.
+ For more info see <a href="http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt">DNS-Based Service Discovery</a>, section 6.
*/
public class TXTRecord
*/
public void set( String key, byte[] value)
{
- byte[] oldBytes = fBytes;
byte[] keyBytes;
int valLen = (value != null) ? value.length : 0;
- byte newLen;
try {
keyBytes = key.getBytes( "US-ASCII");
if ( keyBytes.length + valLen >= 255)
throw new ArrayIndexOutOfBoundsException();
- newLen = (byte) ( keyBytes.length + valLen + (valLen > 0 ? 1 : 0));
- fBytes = new byte[ oldBytes.length + newLen + 1];
- System.arraycopy( oldBytes, 0, fBytes, 0, oldBytes.length);
- fBytes[ oldBytes.length] = newLen;
- System.arraycopy( keyBytes, 0, fBytes, oldBytes.length + 1, keyBytes.length);
- if ( valLen > 0)
+ int prevLoc = this.remove( key);
+ if ( prevLoc == -1)
+ prevLoc = this.size();
+
+ this.insert( keyBytes, value, prevLoc);
+ }
+
+ protected void insert( byte[] keyBytes, byte[] value, int index)
+ // Insert a key-value pair at index
+ {
+ byte[] oldBytes = fBytes;
+ int valLen = (value != null) ? value.length : 0;
+ int insertion = 0;
+ int newLen, avLen;
+
+ // locate the insertion point
+ for ( int i=0; i < index && insertion < fBytes.length; i++)
+ insertion += (0xFF & (fBytes[ insertion] + 1));
+
+ avLen = keyBytes.length + valLen + (value != null ? 1 : 0);
+ newLen = avLen + oldBytes.length + 1;
+
+ fBytes = new byte[ newLen];
+ System.arraycopy( oldBytes, 0, fBytes, 0, insertion);
+ int secondHalfLen = oldBytes.length - insertion;
+ System.arraycopy( oldBytes, insertion, fBytes, newLen - secondHalfLen, secondHalfLen);
+ fBytes[ insertion] = ( byte) avLen;
+ System.arraycopy( keyBytes, 0, fBytes, insertion + 1, keyBytes.length);
+ if ( value != null)
{
- fBytes[ oldBytes.length + 1 + keyBytes.length] = kAttrSep;
- System.arraycopy( value, 0, fBytes, oldBytes.length + keyBytes.length + 2, value.length);
+ fBytes[ insertion + 1 + keyBytes.length] = kAttrSep;
+ System.arraycopy( value, 0, fBytes, insertion + keyBytes.length + 2, valLen);
}
}
+ /** Remove a key/value pair from the TXT record. Returns index it was at, or -1 if not found. */
+ public int remove( String key)
+ {
+ int avStart = 0;
+
+ for ( int i=0; avStart < fBytes.length; i++)
+ {
+ int avLen = fBytes[ avStart];
+ if ( key.length() <= avLen &&
+ ( key.length() == avLen || fBytes[ avStart + key.length() + 1] == kAttrSep))
+ {
+ String s = new String( fBytes, avStart + 1, key.length());
+ if ( 0 == key.compareToIgnoreCase( s))
+ {
+ byte[] oldBytes = fBytes;
+ fBytes = new byte[ oldBytes.length - avLen - 1];
+ System.arraycopy( oldBytes, 0, fBytes, 0, avStart);
+ System.arraycopy( oldBytes, avStart + avLen + 1, fBytes, avStart, oldBytes.length - avStart - avLen - 1);
+ return i;
+ }
+ }
+ avStart += (0xFF & (avLen + 1));
+ }
+ return -1;
+ }
+
/** Return the number of keys in the TXT record. */
public int size()
{
int i, avStart;
for ( i=0, avStart=0; avStart < fBytes.length; i++)
- avStart += fBytes[ avStart] + 1;
+ avStart += (0xFF & (fBytes[ avStart] + 1));
return i;
}
{
value = new byte[ avLen - aLen - 1];
System.arraycopy( fBytes, avStart + aLen + 2, value, 0, avLen - aLen - 1);
+ break;
}
}
}
/** Return the contents of the TXT record as raw bytes. */
public byte[] getRawBytes() { return (byte[]) fBytes.clone(); }
+
+ /** Return a string representation of the object. */
+ public String toString()
+ {
+ String a, result = null;
+
+ for ( int i=0; null != ( a = this.getKey( i)); i++)
+ {
+ String av = String.valueOf( i) + "={" + a;
+ String val = this.getValueAsString( i);
+ if ( val != null)
+ av += "=" + val + "}";
+ else
+ av += "}";
+ if ( result == null)
+ result = av;
+ else
+ result = result + ", " + av;
+ }
+ return result != null ? result : "";
+ }
}