1 package fi.vtt.simantics.procore.internal;
3 import org.simantics.db.DirectStatements;
4 import org.simantics.db.ReadGraph;
5 import org.simantics.db.RelationInfo;
6 import org.simantics.db.Resource;
7 import org.simantics.db.exception.AssumptionException;
8 import org.simantics.db.exception.DatabaseException;
9 import org.simantics.db.exception.NoSingleResultException;
10 import org.simantics.db.impl.ClusterI;
11 import org.simantics.db.impl.ClusterI.ClusterTypeEnum;
12 import org.simantics.db.impl.ForEachObjectContextProcedure;
13 import org.simantics.db.impl.ForEachObjectProcedure;
14 import org.simantics.db.impl.ForPossibleRelatedValueContextProcedure;
15 import org.simantics.db.impl.ForPossibleRelatedValueProcedure;
16 import org.simantics.db.impl.ResourceImpl;
17 import org.simantics.db.impl.TransientGraph;
18 import org.simantics.db.impl.graph.ReadGraphImpl;
19 import org.simantics.db.procedure.SyncContextMultiProcedure;
20 import org.simantics.db.procedure.SyncContextProcedure;
21 import org.simantics.db.procedure.SyncMultiProcedure;
22 import org.simantics.db.procedure.SyncProcedure;
23 import org.simantics.db.procore.cluster.ClusterBig;
24 import org.simantics.db.procore.cluster.ClusterImpl;
25 import org.simantics.db.procore.cluster.ClusterSmall;
26 import org.simantics.db.procore.cluster.ResourceTableSmall;
27 import org.simantics.db.procore.cluster.ValueTableSmall;
28 import org.simantics.db.service.DirectQuerySupport;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
32 public class DirectQuerySupportImpl implements DirectQuerySupport {
34 private static final Logger LOGGER = LoggerFactory.getLogger(DirectQuerySupportImpl.class);
36 final private SessionImplSocket session;
38 DirectQuerySupportImpl(SessionImplSocket session) {
39 this.session = session;
43 final public DirectStatements getDirectPersistentStatements(ReadGraph graph, final Resource subject) {
44 ReadGraphImpl impl = (ReadGraphImpl)graph;
45 return impl.processor.getDirectStatements(impl, subject, true);
49 final public DirectStatements getDirectStatements(ReadGraph graph, final Resource subject) {
50 ReadGraphImpl impl = (ReadGraphImpl)graph;
51 return impl.processor.getDirectStatements(impl, subject, false);
55 public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, SyncProcedure<DirectStatements> procedure) {
56 forEachDirectStatement(graph, subject, new SyncToAsyncProcedure<DirectStatements>(procedure));
60 public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, Procedure<DirectStatements> procedure) {
61 ReadGraphImpl impl = (ReadGraphImpl)graph;
62 impl.processor.forEachDirectStatement(impl, subject, procedure);
66 public void forRelationInfo(AsyncReadGraph graph, Resource subject, AsyncProcedure<RelationInfo> procedure) {
67 ReadGraphImpl impl = (ReadGraphImpl)graph;
68 impl.processor.forRelationInfo(impl, subject, procedure);
72 public void forRelationInfo(AsyncReadGraph graph, Resource subject, SyncProcedure<RelationInfo> procedure) {
73 forRelationInfo(graph, subject, new SyncToAsyncProcedure<RelationInfo>(procedure));
77 public void forRelationInfo(AsyncReadGraph graph, Resource subject, Procedure<RelationInfo> procedure) {
78 forRelationInfo(graph, subject, new NoneToAsyncProcedure<RelationInfo>(procedure));
82 public RelationInfo getRelationInfo(ReadGraph graph, Resource subject) throws DatabaseException {
83 ReadGraphImpl impl = (ReadGraphImpl)graph;
84 return impl.processor.getRelationInfo(impl, subject);
88 public SyncMultiProcedure<Resource> compileForEachObject(ReadGraph graph, final Resource relation, SyncMultiProcedure<Resource> user) throws DatabaseException {
90 RelationInfo info = getRelationInfo(graph, relation);
91 final int predicateKey = ((ResourceImpl)relation).id;
92 return new ForEachObjectProcedure(predicateKey, info, session.queryProvider2, user);
97 public <C> SyncContextMultiProcedure<C, Resource> compileForEachObject(ReadGraph graph, final Resource relation, SyncContextMultiProcedure<C, Resource> user) throws DatabaseException {
99 RelationInfo info = getRelationInfo(graph, relation);
100 final int predicateKey = ((ResourceImpl)relation).id;
101 return new ForEachObjectContextProcedure<C>(predicateKey, info, session.queryProvider2, user);
106 public <T> SyncProcedure<T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, SyncProcedure<T> user) throws DatabaseException {
108 RelationInfo info = getRelationInfo(graph, relation);
109 final int predicateKey = ((ResourceImpl)relation).id;
110 return new ForPossibleRelatedValueProcedure<T>(predicateKey, info, user);
115 public <C, T> SyncContextProcedure<C, T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, SyncContextProcedure<C, T> user) throws DatabaseException {
117 RelationInfo info = getRelationInfo(graph, relation);
118 final int predicateKey = ((ResourceImpl)relation).id;
119 return new ForPossibleRelatedValueContextProcedure<C, T>(predicateKey, info, user);
124 public void forEachObjectCompiled(ReadGraph graph, Resource subject, final SyncMultiProcedure<Resource> procedure) {
126 assert(subject != null);
128 final ForEachObjectProcedure proc = (ForEachObjectProcedure)procedure;
129 // final RelationInfo info = proc.info;
131 final ReadGraphImpl impl = (ReadGraphImpl)graph;
132 final int subjectId = ((ResourceImpl)subject).id;
134 // int callerThread = impl.callerThread;
135 // int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
139 // if(callerThread == suggestSchedule) {
141 // if(info.isFunctional) {
142 // querySupport.getObjects4(impl, subjectId, proc);
144 session.querySupport.getObjects4(impl, subjectId, proc);
149 // impl.state.barrier.inc();
150 // impl.state.barrier.dec(callerThread);
152 // queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
155 // public void run(int thread) {
157 // impl.state.barrier.inc(thread);
158 // impl.state.barrier.dec();
160 // if(info.isFunctional) {
161 // querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
163 // querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
169 // public String toString() {
180 public <C> void forEachObjectCompiled(ReadGraph graph, Resource subject, C context, final SyncContextMultiProcedure<C, Resource> procedure) {
182 assert(subject != null);
184 final ForEachObjectContextProcedure<C> proc = (ForEachObjectContextProcedure<C>)procedure;
185 final RelationInfo info = proc.info;
187 final ReadGraphImpl impl = (ReadGraphImpl)graph;
188 final int subjectId = ((ResourceImpl)subject).id;
190 // int callerThread = impl.callerThread;
191 // int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
195 if(info.isFunctional) {
196 session.querySupport.getObjects4(impl, subjectId, context, proc);
198 session.querySupport.getObjects4(impl, subjectId, context, proc);
204 public <T> void forPossibleRelatedValueCompiled(ReadGraph graph, Resource subject, final SyncProcedure<T> procedure) {
206 assert(subject != null);
208 final ForPossibleRelatedValueProcedure<T> proc = (ForPossibleRelatedValueProcedure<T>)procedure;
209 final RelationInfo info = proc.info;
211 final ReadGraphImpl impl = (ReadGraphImpl)graph;
212 final int subjectId = ((ResourceImpl)subject).id;
214 // int callerThread = impl.callerThread;
215 // int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
219 // if(callerThread == suggestSchedule) {
221 // if(info.isFunctional) {
223 T result = getRelatedValue4(impl, subjectId, proc);
225 proc.execute(graph, result);
226 } catch (DatabaseException e2) {
227 LOGGER.error("Unexpected exception while handling related value", e2);
229 } catch (DatabaseException e) {
231 proc.exception(graph, e);
232 } catch (DatabaseException e2) {
233 LOGGER.error("Unexpected exception while handling related value", e2);
237 // getRelatedValue4(impl, subjectId, proc);
242 // impl.state.barrier.inc();
243 // impl.state.barrier.dec(callerThread);
245 // queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
248 // public void run(int thread) {
250 // impl.state.barrier.inc(thread);
251 // impl.state.barrier.dec();
253 // if(info.isFunctional) {
254 // getRelatedValue4(impl.newAsync(thread), subjectId, proc);
256 // getRelatedValue4(impl.newAsync(thread), subjectId, proc);
262 // public String toString() {
273 public <C, T> void forPossibleRelatedValueCompiled(ReadGraph graph, Resource subject, C context, final SyncContextProcedure<C, T> procedure) {
275 assert(subject != null);
277 final ForPossibleRelatedValueContextProcedure<C, T> proc = (ForPossibleRelatedValueContextProcedure<C, T>)procedure;
278 final RelationInfo info = proc.info;
280 final ReadGraphImpl impl = (ReadGraphImpl)graph;
281 final int subjectId = ((ResourceImpl)subject).id;
283 // int callerThread = impl.callerThread;
284 // int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
288 // if(info.isFunctional) {
290 // getRelatedValue4(impl, subjectId, context, proc);
294 T result = getRelatedValue4(impl, subjectId, context, proc);
295 proc.execute(graph, context, result);
296 } catch (DatabaseException e) {
297 proc.exception(graph, e);
303 public <T> void forPossibleType(final AsyncReadGraph graph, Resource subject, final AsyncProcedure<Resource> procedure) {
305 assert(subject != null);
307 final ReadGraphImpl impl = (ReadGraphImpl)graph;
308 final int subjectId = ((ResourceImpl)subject).id;
312 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
313 if(!cluster.isLoaded()) {
315 // impl.state.inc(0);
317 session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
324 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
325 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
327 // impl.state.dec(0);
329 } catch (DatabaseException e) {
339 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
340 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
344 } catch (DatabaseException e) {
355 public <C> void forPossibleDirectType(final ReadGraph graph, Resource subject, final C context, final SyncContextProcedure<C, Resource> procedure) {
357 assert(subject != null);
359 final ReadGraphImpl impl = (ReadGraphImpl)graph;
360 final int subjectId = ((ResourceImpl)subject).id;
364 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
365 if(!cluster.isLoaded()) {
367 // impl.state.inc(0);
369 session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
376 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);
377 if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
378 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
379 procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));
381 procedure.execute(graph, context, null);
384 // impl.state.dec(0);
386 } catch (DatabaseException e) {
396 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);
397 if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
398 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
399 procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));
401 procedure.execute(graph, context, null);
406 } catch (DatabaseException e) {
408 procedure.execute(graph, context, null);
410 } catch (Throwable t) {
413 procedure.execute(graph, context, null);
419 private <C, T> T getRelatedValue4(final ReadGraphImpl graph, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) throws DatabaseException {
423 final int predicate = procedure.predicateKey;
427 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
428 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, g -> {});
429 return getRelatedValue4(graph, subject, context, procedure);
432 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
433 for (int id : g.getObjects(subject, predicate)) {
435 throw new DatabaseException("Multiple objects");
443 throw new DatabaseException("No objects for " + subject );
445 return getValue4(graph, null, result, context, procedure);
450 final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
451 if(!cluster.isLoaded()) {
453 return getRelatedValue4(graph, subject, context, procedure);
456 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
458 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
459 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, g -> {});
460 return getRelatedValue4(graph, subject, context, procedure);
463 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
464 for (int id : g.getObjects(subject, predicate)) {
466 throw new DatabaseException("Multiple objects");
473 return getRelatedDirectValue4(graph, cluster, subject, result, context, procedure);
477 return getRelatedDirectValue4(graph, cluster, subject, 0, context, procedure);
483 private <T> T getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) throws DatabaseException {
485 Object result = null;
489 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
490 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, g -> {});
491 return getValue4(graph, containerCluster, subject, procedure);
494 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
495 Object value = g.getValue(subject);
498 throw new DatabaseException("Multiple values");
509 ClusterImpl cluster = containerCluster;
510 if(!containerCluster.contains(subject)) {
511 cluster = session.clusterTable.getClusterByResourceKey(subject);
512 if(!cluster.isLoaded()) {
514 return getValue4(graph, containerCluster, subject, procedure);
518 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
520 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
521 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, g -> {});
522 return getValue4(graph, containerCluster, subject, procedure);
525 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
526 Object value = g.getValue(subject);
529 throw new DatabaseException("Multiple values");
539 if(ClusterTypeEnum.SMALL == cluster.getType())
540 return getDirectValue4(graph, (ClusterSmall)cluster, subject);
542 return getDirectValue4(graph, (ClusterBig)cluster, subject);
547 if(ClusterTypeEnum.SMALL == cluster.getType())
548 return getDirectValue4(graph, (ClusterSmall)cluster, subject);
550 return getDirectValue4(graph, (ClusterBig)cluster, subject);
556 private <C, T> T getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) throws DatabaseException {
558 Object result = null;
562 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
563 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, g -> {});
564 return getValue4(graph, containerCluster, subject, context, procedure);
567 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
568 Object value = g.getValue(subject);
571 throw new DatabaseException("Multiple values");
582 ClusterImpl cluster = containerCluster;
583 if(!containerCluster.contains(subject)) {
584 cluster = session.clusterTable.getClusterByResourceKey(subject);
585 if(!cluster.isLoaded()) {
587 return getValue4(graph, containerCluster, subject, context, procedure);
591 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
593 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
594 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, g -> {});
595 return getValue4(graph, containerCluster, subject, context, procedure);
598 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
599 Object value = g.getValue(subject);
602 throw new DatabaseException("Multiple values");
612 if(ClusterTypeEnum.SMALL == cluster.getType())
613 return getDirectValue4(graph, (ClusterSmall)cluster, subject);
615 return getDirectValue4(graph, (ClusterBig)cluster, subject);
620 if(ClusterTypeEnum.SMALL == cluster.getType())
621 return getDirectValue4(graph, (ClusterSmall)cluster, subject);
623 return getDirectValue4(graph, (ClusterBig)cluster, subject);
629 private <T> T getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final ForPossibleRelatedValueProcedure<T> procedure) throws DatabaseException {
631 int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
634 throw new DatabaseException("No objects " + subject + " " + procedure.predicateKey);
636 return getValue4(graph, cluster, result, procedure);
640 return getValue4(graph, cluster, so, procedure);
642 throw new DatabaseException("Multiple objects");
648 private <C, T> T getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) throws DatabaseException {
650 int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
653 throw new NoSingleResultException("No objects " + subject + " " + procedure.predicateKey, result);
655 return getValue4(graph, cluster, result, context, procedure);
659 return getValue4(graph, cluster, so, context, procedure);
661 throw new NoSingleResultException("Multiple objects for " + subject + " " + procedure.predicateKey, result);
667 public <T> T getRelatedValue4(final ReadGraphImpl graph, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) throws DatabaseException {
671 final int predicate = procedure.predicateKey;
675 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
676 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, g -> {});
677 return getRelatedValue4(graph, subject, procedure);
680 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
681 for (int id : g.getObjects(subject, predicate)) {
683 throw new DatabaseException("Multiple objects");
691 throw new DatabaseException("No objects for " + subject );
693 return getValue4(graph, null, result, procedure);
698 final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
699 if(!cluster.isLoaded()) {
701 return getRelatedValue4(graph, subject, procedure);
704 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
706 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
707 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, g -> {});
708 return getRelatedValue4(graph, subject, procedure);
711 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
712 for (int id : g.getObjects(subject, predicate)) {
714 throw new DatabaseException("Multiple objects");
721 return getRelatedDirectValue4(graph, cluster, subject, result, procedure);
725 return getRelatedDirectValue4(graph, cluster, subject, 0, procedure);
732 private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
735 byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
736 T value = (T)utf(bytes);
737 procedure.execute(graph, context, value);
738 } catch (DatabaseException e) {
739 procedure.execute(graph, context, null);
747 private <T> T getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject) throws DatabaseException {
749 byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
750 return (T)utf(bytes);
754 private <T> T getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject) {
756 ResourceTableSmall rt = cluster.resourceTable;
757 ValueTableSmall vt = cluster.valueTable;
759 byte[] bs = vt.table;
760 long[] ls = rt.table;
762 int index = ((subject&0xFFF) << 1) - 1 + rt.offset;
764 int valueIndex = (int)(ls[index] >>> 24) & 0x3FFFFF + vt.offset;
766 int size = (int)bs[valueIndex++]-1;
767 char[] chars = new char[size];
769 for(int i=0;i<size;i++) {
770 chars[i] = (char)bs[valueIndex++];
773 return (T)new String(chars);
777 final private String utf(byte[] bytes) throws AssumptionException {
779 if(bytes == null) return null;
781 // Read databoard int32 using Length encoding
782 // https://dev.simantics.org/index.php/Databoard_Specification#Length
784 int length = bytes[index++]&0xff;
790 length += ((bytes[index++]&0xff)<<3);
791 length += ((bytes[index++]&0xff)<<11);
792 length += ((bytes[index++]&0xff)<<19);
793 length += 0x10204080;
797 length += ((bytes[index++]&0xff)<<4);
798 length += ((bytes[index++]&0xff)<<12);
799 length += ((bytes[index++]&0xff)<<20);
805 length += ((bytes[index++]&0xff)<<5);
806 length += ((bytes[index++]&0xff)<<13);
812 length += ((bytes[index++]&0xff)<<6);
817 // Copied from DataInputStream
819 char[] chararr = new char[utflen];
823 int target = index + length;
826 while (count < target) {
827 c = (int) bytes[count] & 0xff;
830 chararr[chararr_count++]=(char)c;
833 while (count < target) {
834 c = (int) bytes[count] & 0xff;
836 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
839 chararr[chararr_count++]=(char)c;
842 /* 110x xxxx 10xx xxxx*/
845 throw new AssumptionException(
846 "malformed input: partial character at end (" + (count-index) + " > " + utflen + ")");
847 char2 = (int) bytes[count-1];
848 if ((char2 & 0xC0) != 0x80)
849 throw new AssumptionException(
850 "malformed input around byte " + count);
851 chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
855 /* 1110 xxxx 10xx xxxx 10xx xxxx */
858 throw new AssumptionException(
859 "malformed input: partial character at end (" + (count-index) + " > " + utflen + ")");
860 char2 = (int) bytes[count-2];
861 char3 = (int) bytes[count-1];
862 if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
863 throw new AssumptionException(
864 "malformed input around byte " + (count-1));
865 chararr[chararr_count++]=(char)(((c & 0x0F) << 12) |
866 ((char2 & 0x3F) << 6) |
867 ((char3 & 0x3F) << 0));
870 /* 10xx xxxx, 1111 xxxx */
871 throw new AssumptionException(
872 "malformed input around byte " + count);
876 // The number of chars produced may be less than utflen
877 return new String(chararr, 0, chararr_count);